﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web.UI.WebControls.WebParts;
using System.Xml;
using System.Xml.Linq;
using System.Text;
using Microsoft.Office.RecordsManagement.InformationPolicy; // references MS Chart Controls for .Net 3.5 http://www.microsoft.com/downloads/details.aspx?FamilyId=130F7986-BF49-4FE5-9CA8-910AE6EA442C&displaylang=en
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Navigation;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebPartPages;
using SharePointSiteConfigurator.Extensions;
using DNWebPart = System.Web.UI.WebControls.WebParts.WebPart;
using SPWebPart = Microsoft.SharePoint.WebPartPages.WebPart;
using System.Web;

namespace SharePointSiteConfigurator {
    public class SharePointUtilities {

#if SP2010
        private static TraceLogger2010 mtr;
#else
        private static TraceLogger mtr;
#endif
        static SharePointUtilities() {

#if SP2010
            mtr = new TraceLogger2010(); // TraceLogger2010.Instance;
#else
            mtr = TraceLogger.Instance;
#endif
        }

        /// <summary>
        /// Set web properties from the configuration file.
        /// XML must provide key value pairs as:
        /// <Property Name="SPWebPropery" Value="ValueToSet" />
        /// IE. <Property Name="Time24" Value="true" />
        /// </summary>
        /// <param name="web"></param>
        /// <param name="items"></param>
        public static void SetWebProperty(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting SetWebProperties()");
            try {
                if (item.Attribute("Name") != null) {
                    mtr.TraceVerboseMessage("Setting webproperty: " + item.Attribute("Name"));
                    string propertyName = item.Attribute("Name").Value;
                    string propertyValue = item.Attribute("Value").Value;
                    // find the property 
                    PropertyInfo propertyInfo = typeof(SPWeb).GetProperty(propertyName);
                    string typeSwitch = propertyInfo.PropertyType.ToString();
                    switch (typeSwitch) {
                        case "System.String":
                            propertyInfo.SetValue(web, propertyValue, null);
                            break;
                        case "System.Boolean":
                            propertyInfo.SetValue(web, bool.Parse(propertyValue), null);
                            break;
                        case "System.Int16":
                        case "System.Int32":
                            propertyInfo.SetValue(web, int.Parse(propertyValue), null);
                            break;
                        default:
                            throw new InvalidCastException();
                    }
                    web.Update();
                }
            } catch (Exception ex) {
                mtr.TraceError("Could not set a web property.", ex);
            }
            mtr.TraceVerboseMessage("Completed SetWebProperties()");
        }

        /// <summary>
        /// Sets the master url, relative to the root site
        /// </summary>
        /// <param name="web"></param>
        /// <param name="masterUrl"></param>
        /// <returns></returns>
        public static void SetMasterUrlProperty(SPWeb web, XElement item) {
            try {
                if (web == null) throw new ArgumentNullException("web", "Cannot be null");
                if (item == null) throw new ArgumentNullException("item", "Cannot be null");
                string masterUrl = string.Empty;
                if (item.Attribute("Url").Value != null) masterUrl = item.Attribute("Url").Value;
                mtr.TraceVerboseMessage("Starting SetMasterUrlProperty()");
                mtr.TraceVerboseMessage("masterUrl = '" + masterUrl + "'");
                if (!string.IsNullOrEmpty(masterUrl)) {
                    web.MasterUrl = masterUrl;
                    web.Update();
                }
            } catch (Exception ex) {
                mtr.TraceError("Unable to set master url property", ex);
            }
        }


        public static bool SetRegionalSetting(SPWeb web, XElement item) {
            bool success = false;
            mtr.TraceVerboseMessage("Starting SetRegionalSettings()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return success;

            try {
                switch (item.Attribute("Name").Value) {
                    case "LocaleId":
                        mtr.TraceVerboseMessage("Setting LocaleId...");
                        web.RegionalSettings.LocaleId = uint.Parse(item.Attribute("Value").Value);
                        break;
                    case "TimeZoneId":
                        mtr.TraceVerboseMessage("Setting TimeZoneId...");
                        web.RegionalSettings.TimeZone.ID = ushort.Parse(item.Attribute("Value").Value);
                        break;
                    case "CalendarType":
                        mtr.TraceVerboseMessage("Setting CalendarType...");
                        web.RegionalSettings.CalendarType = short.Parse(item.Attribute("Value").Value);
                        break;
                    case "ShowWeeks":
                        mtr.TraceVerboseMessage("Setting ShowWeeks...");
                        web.RegionalSettings.ShowWeeks = bool.Parse(item.Attribute("Value").Value);
                        break;
                    case "Time24":
                        mtr.TraceVerboseMessage("Setting Time24...");
                        web.RegionalSettings.Time24 = bool.Parse(item.Attribute("Value").Value);
                        break;
                    case "Collation":
                        mtr.TraceVerboseMessage("Setting Collation...");
                        web.RegionalSettings.Collation = short.Parse(item.Attribute("Value").Value);
                        break;
                    case "FirstDayOfWeek":
                        mtr.TraceVerboseMessage("Setting FirstDayOfWeek...");
                        web.RegionalSettings.FirstDayOfWeek = uint.Parse(item.Attribute("Value").Value);
                        break;
                    case "FirstWeekOfYear":
                        mtr.TraceVerboseMessage("Setting FirstWeekOfYear...");
                        web.RegionalSettings.FirstWeekOfYear = short.Parse(item.Attribute("Value").Value);
                        break;
                    case "WorkDays":
                        mtr.TraceVerboseMessage("Setting WorkDays...");
                        web.RegionalSettings.WorkDays = short.Parse(item.Attribute("Value").Value);
                        break;
                    case "WorkDayStartHour":
                        mtr.TraceVerboseMessage("Setting WorkDayStartHour...");
                        web.RegionalSettings.WorkDayStartHour = short.Parse(item.Attribute("Value").Value);
                        break;
                    case "WorkDayEndHour":
                        mtr.TraceVerboseMessage("Setting WorkDayEndHour...");
                        web.RegionalSettings.WorkDayEndHour = short.Parse(item.Attribute("Value").Value);
                        break;
                }
            } catch (Exception ex) {
                mtr.TraceError("Unable to set regional settings", ex);
            } finally {
                web.Update();
            }
            return success;
        }

        public static bool SetRoleInheritance(SPWeb web, XElement item) {
            bool success = false;
            mtr.TraceVerboseMessage("Starting SetRoleInheritance()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return success; ;
            try {
                if (item != null) {
                    if (item.Attribute("Value") != null) {
                        string roleInheritance = item.Attribute("Value").Value.ToLower();
                        switch (roleInheritance) {
                            case "breakcopy":
                                if (!web.HasUniqueRoleAssignments) {
                                    mtr.TraceVerboseMessage("Breaking inheritance, copying role assignments");
                                    web.BreakRoleInheritance(true);
                                }
                                success = true;
                                break;
                            case "breaknocopy":
                                if (!web.HasUniqueRoleAssignments) {
                                    mtr.TraceVerboseMessage("Breaking inheritance, NOT copying role assignments");
                                    web.BreakRoleInheritance(false);
                                }
                                success = true;
                                break;
                            case "inherit":
                                if (web.HasUniqueRoleAssignments) {
                                    mtr.TraceVerboseMessage("Resetting role inheritance");
                                    web.ResetRoleInheritance();
                                }
                                success = true;
                                break;
                            default:
                                throw new ArgumentException("Invalid role inheritance property: " + roleInheritance + " Valid values: BreakCopy, BreakNoCopy, Inherit");
                        }
                    }
                }
            } catch (Exception ex) {
                mtr.TraceError("Unable to set role inheritance", ex);
            }
            return success;
        }


        public static bool AddTopNavigationLink(SPWeb web, XElement item) {
            bool success = false;
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return success; ;
            try {
                mtr.TraceVerboseMessage("Starting AddTopNavigationLinks()");
                mtr.TraceVerboseMessage("Adding topnavigationbaritem with title = '" + item.Attribute("Title").Value + "'");
                SPNavigationNode node = new SPNavigationNode(item.Attribute("Title").Value, item.Attribute("Link").Value, bool.Parse(item.Attribute("IsExternal").Value));
                web.Navigation.TopNavigationBar.AddAsLast(node);
                web.Update();
                success = true;
            } catch (Exception ex) {
                mtr.TraceError("Unable to add top navigation links", ex);
            }
            return success;
        }

        public static bool DeleteTopNavigationLinks(SPWeb web) {
            bool success = false;
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            try {
                mtr.TraceVerboseMessage("Starting DeleteTopNavigationLinks()");
                SPNavigationNodeCollection topNavigationBar = web.Navigation.TopNavigationBar;

                for (int index = topNavigationBar.Count - 1; index >= 0; index--) {
                    mtr.TraceVerboseMessage("Deleting topNavigationBar item = '" + index + "'");
                    topNavigationBar[index].Delete();
                }
                web.Update();
                success = true;
            } catch (Exception ex) {
                mtr.TraceError("Unable to delete top navigation links", ex);
            }
            return success;
        }

        public static bool DeleteExplicitTopNavigationLinks(SPWeb web, XElement item) {
            bool success = false;
            try {
                mtr.TraceVerboseMessage("Starting DeleteExplicitTopNavigationLinks()");
                SPNavigationNodeCollection topNavigationBar = web.Navigation.TopNavigationBar;

                for (int i = topNavigationBar.Count - 1; i >= 0; i--) {
                    if (topNavigationBar[i].Url.Equals(item.Attribute("Link").Value)) {
                        mtr.TraceVerboseMessage("Deleting topnavigation heading with name: " + item.Attribute("Link").Value);
                        topNavigationBar[i].Delete();
                    }
                }
                web.Update();
                success = true;
            } catch (Exception ex) {
                mtr.TraceError("Unable to explicit delete top navigation links", ex);
            }
            return success;
        }

        public static void ConfigurePublishingNavigation(SPWeb web, XElement item) {
            if (PublishingWeb.IsPublishingWeb(web)) {
                PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web);
                //Global settings (the top bar)
                if (item.Attribute("inheritTopNavRadioButton") != null) {
                    publishingWeb.Navigation.InheritGlobal = bool.Parse(item.Attribute("inheritTopNavRadioButton").Value);
                }
                if (item.Attribute("GlobalIncludePages") != null) {
                    publishingWeb.Navigation.GlobalIncludePages = bool.Parse(item.Attribute("GlobalIncludePages").Value);
                }
                if (item.Attribute("GlobalIncludeSubSites") != null) {
                    publishingWeb.Navigation.GlobalIncludeSubSites = bool.Parse(item.Attribute("GlobalIncludeSubSites").Value);
                }

                //Current nav settings (the bar on the left)
                if (item.Attribute("InheritCurrent") != null) {
                    publishingWeb.Navigation.InheritCurrent = bool.Parse(item.Attribute("InheritCurrent").Value);
                }
                if (item.Attribute("ShowSiblings") != null) {
                    publishingWeb.Navigation.ShowSiblings = bool.Parse(item.Attribute("ShowSiblings").Value);
                }
                if (item.Attribute("CurrentIncludePages") != null) {
                    publishingWeb.Navigation.CurrentIncludePages = bool.Parse(item.Attribute("CurrentIncludePages").Value);
                }
                if (item.Attribute("CurrentIncludeSubSites") != null) {
                    publishingWeb.Navigation.CurrentIncludeSubSites = bool.Parse(item.Attribute("CurrentIncludeSubSites").Value);
                }
                //sorting
                //Sort by Title, Created or Modified: Ascending or desc
                if (item.Attribute("OrderingMethod") != null) {
                    publishingWeb.Navigation.OrderingMethod = (OrderingMethod)Enum.Parse(typeof(OrderingMethod), item.Attribute("OrderingMethod").Value);
                    if (publishingWeb.Navigation.OrderingMethod != OrderingMethod.Manual) {
                        if (item.Attribute("AutomaticSortingMethod") != null) {
                            publishingWeb.Navigation.AutomaticSortingMethod = (AutomaticSortingMethod)Enum.Parse(typeof(AutomaticSortingMethod), item.Attribute("AutomaticSortingMethod").Value);
                        }
                        if (item.Attribute("SortAscending") != null) {
                            publishingWeb.Navigation.SortAscending = bool.Parse(item.Attribute("SortAscending").Value);
                        }
                    }
                }
                publishingWeb.Navigation.CurrentNavigationNodes.Parent.Update();
            }
        }

        public static bool AddQuickLaunchHeading(SPWeb web, XElement item) {
            bool success = false;
            SPNavigationNodeCollection headingNodes = web.Navigation.QuickLaunch;

            mtr.TraceVerboseMessage("Starting AddQuickLaunchHeadings()");
            try {
                string title = item.Attribute("Title").Value;
                string lenke = item.Attribute("Link").Value;
                bool dupExists = false;
                mtr.TraceVerboseMessage("Adding quick launch heading. Title: " + title + " Link: " + lenke);
                foreach (SPNavigationNode n in headingNodes) {
                    if ((n.Title == title) && (n.Url.EndsWith(lenke))) {
                        dupExists = true;
                        break;
                    }
                }
                if (!dupExists) {
                    SPNavigationNode node = new SPNavigationNode(item.Attribute("Title").Value, item.Attribute("Link").Value, bool.Parse(item.Attribute("IsExternal").Value));
                    headingNodes.AddAsLast(node);
                    web.Update();
                    success = true;
                }
            } catch (Exception ex) {
                mtr.TraceError("Unable to add quick launch heading", ex);
            }
            return success;
        }

        /// <summary>
        /// Deletes all quick launch headings with a given title
        /// </summary>
        public static void DeleteQuickLaunchHeading(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting DeleteQuickLaunchHeadings()");
            try {
                bool foundHeading = true;
                while (foundHeading) {
                    SPNavigationNode nodeToDelete = GetNodeByTitle(web.Navigation.QuickLaunch, item.Attribute("Title").Value);

                    if (nodeToDelete == null) {
                        foundHeading = false;
                    } else {
                        mtr.TraceVerboseMessage("Deleting " + nodeToDelete.Title);
                        web.Navigation.QuickLaunch.Delete(nodeToDelete);
                    }
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Delete quick launch headings failed", ex);
            }
        }

        public static void AddQuickLaunchLink(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting AddQuickLaunchLink()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item.Attribute("Title") == null) throw new ArgumentException("Title", "Cannot be null");

            try {
                mtr.TraceVerboseMessage(string.Format("Adding link with title: {0} and link: {1}", item.Attribute("Title").Value, item.Attribute("Link").Value));
                SPNavigationNode newNode = new SPNavigationNode(item.Attribute("Title").Value, item.Attribute("Link").Value, bool.Parse(item.Attribute("IsExternal").Value));
                SPNavigationNode parentNode = GetNodeByTitle(web.Navigation.QuickLaunch, item.Attribute("Heading").Value);
                parentNode.Children.AddAsLast(newNode);
                mtr.TraceVerboseMessage("LinkAdded as last node");
            } catch (Exception ex) {
                mtr.TraceError("Unable to add quick launch links", ex);
            }
        }

        /// <summary>
        /// For a given quick launch heading, delete all quick launch links
        /// </summary>
        public static bool DeleteQuickLaunchLinks(SPWeb web) {
            mtr.TraceVerboseMessage("Starting DeleteQuickLaunchLinks()");
            bool success = false;
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");

            try {
                foreach (SPNavigationNode quickLaunchNode in web.Navigation.QuickLaunch) {
                    for (int index = quickLaunchNode.Children.Count - 1; index >= 0; index--) {
                        mtr.TraceVerboseMessage("Deleting quick launch node " + quickLaunchNode.Children[index].Title);
                        quickLaunchNode.Children[index].Delete();
                    }
                }
                success = true;
            } catch (Exception ex) {
                mtr.TraceError("Unable to delete quick launch links", ex);
            }
            return success;
        }
        /// <summary>
        /// For a given quick launch heading, delete all quick launch links
        /// </summary>
        public static void DeleteQuickLaunchLinkItem(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting DeleteQuickLaunchLinkItem()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item.Attribute("Heading") == null) throw new ArgumentException("Heading", "Cannot be null");
            if (item.Attribute("Title") == null) throw new ArgumentException("Title", "Cannot be null");

            try {

                foreach (SPNavigationNode quickLaunchNode in web.Navigation.QuickLaunch) {
                    if (quickLaunchNode.Title == item.Attribute("Heading").Value) {
                        for (int index = quickLaunchNode.Children.Count - 1; index >= 0; index--) {
                            if (quickLaunchNode.Children[index].Title == item.Attribute("Title").Value) {
                                mtr.TraceVerboseMessage("Deleting quick launch node " + quickLaunchNode.Children[index].Title);
                                quickLaunchNode.Children[index].Delete();
                                //web.Update();
                                break;
                            }
                        }
                        break;
                    }
                }
            } catch (Exception ex) {
                mtr.TraceError("Unable to delete quick launch link item", ex);
            }
        }

        /// <summary>
        /// Add webparts to page
        /// Supports AllUsersWebParts in the .dwp format
        /// </summary>
        /// <param name="web">The web to use</param>
        /// <param name="fileName">The file. FileName is specified in each webpart item, but this is used if FileName is empty</param>
        /// <param name="items">WebPart items</param>
        public static void AddWebPart(SPWeb web, XElement item, XElement overrideSection) {
            mtr.TraceVerboseMessage("Starting AddWebPart()");
            try {
                //check if a custom filename is provided as tarrget for the webpart or use the site's welcomepage as fallback
                string fileName = string.Empty;
                if (item.Attribute("FileName") != null) {
                    fileName = item.Attribute("FileName").Value;
                }
                if (!web.GetFile(fileName).Exists) {
                    fileName = web.RootFolder.WelcomePage;
                    if (!web.GetFile(fileName).Exists) {
                        mtr.TraceVerboseMessage(string.Format("Unable to AddWebPart(). There is no file present or provided to add the webparts to."));
                    }
                }

                string errorMessage;
                int webPartOrder = Convert.ToInt32(item.Attribute("WebPartOrder").Value);
                string itemValue = item.Value;

                //Check if web.config override is true
                if ((item.Attribute("AllowConfigOverride") != null) && (item.Attribute("AllowConfigOverrideIdentifier") != null)) {
                    if (bool.Parse(item.Attribute("AllowConfigOverride").Value)) {
                        //parse the ovveride items
                        try {
                            // Get the override value from the overrideconfiguration
                            // <WebPartOverride AllowConfigOverrideIdentifier="YourStringIdentifier">
                            //  <PropertyName1ToOverride Value="TheNewValue" />
                            //  <PropertyName2ToOverride Value="TheNewValue" />
                            //</WebPartOverride>
                            IEnumerable<XElement> wItems =
                            from s in overrideSection.Elements("WebPartOverride")
                            where s.Attribute("AllowConfigOverrideIdentifier").Value.ToLower() == item.Attribute("AllowConfigOverrideIdentifier").Value.ToLower()
                            select s;

                            XmlDocument xDoc = new XmlDocument();
                            xDoc.LoadXml(itemValue);

                            foreach (var propertyOverrideItem in wItems.Elements()) {
                                try {
                                    if (propertyOverrideItem.Attribute("Value") != null) {
                                        XmlNodeList nodes = xDoc.DocumentElement.ChildNodes;
                                        foreach (XmlNode node in nodes) {
                                            try {
                                                if (node.Name.ToLower().Equals(propertyOverrideItem.Name.ToString().ToLower()))
                                                    node.InnerText = propertyOverrideItem.Attribute("Value").Value;
                                            } catch (Exception ex) {

                                                mtr.TraceError("Error reading or setting node value from web.config", ex); ;
                                            }
                                        }
                                    }
                                } catch (Exception ex) {

                                    mtr.TraceError("Error reading or setting override value from web.config", ex);
                                }
                            }
                            StringWriter sw = new StringWriter();
                            XmlTextWriter tw = new XmlTextWriter(sw);
                            xDoc.WriteTo(tw);
                            itemValue = sw.ToString();
                        } catch (Exception ex) {
                            mtr.TraceError("Could not find override key in web.config", ex);
                        }
                    }

                }

                //replace webparttokens with sitespecific data
                XAttribute webpartType = item.Attribute("WebPartType");

                //some housecleaning of the xml
                itemValue = itemValue.Replace("\n", "");

                //Check if you should replace tokens in the webpart xml
                if (item.Attribute("ReplaceTokens") != null) {
                    bool replaceTokens = bool.Parse(item.Attribute("ReplaceTokens").Value);
                    if (replaceTokens) {
                        itemValue = ReplaceTokens(web, itemValue, webpartType);
                    }
                }

                XmlTextReader xmlTextReader = new XmlTextReader(new StringReader(itemValue));
                xmlTextReader.WhitespaceHandling = WhitespaceHandling.None;
                string fileToGet = fileName;
                if (!string.IsNullOrEmpty(fileName)) fileToGet = fileName;
                SPFile file = web.GetFile(fileToGet);

                //Check out the file first if a publishing page
                PublishingWeb pWeb = null;
                PublishingPage page = null;
                if (PublishingWeb.IsPublishingWeb(web) && file != null && PublishingPage.IsPublishingPage(file.Item)) {
                    mtr.TraceVerboseMessage(string.Format("Page was a publishing page {0}", file.Title));
                    pWeb = PublishingWeb.GetPublishingWeb(web);
                    page = pWeb.GetPublishingPage(file.ServerRelativeUrl);
                    // check out page before making changes
                    if (file.Level != SPFileLevel.Checkout) {
                        page.CheckOut();
                        mtr.TraceVerboseMessage(string.Format("Checked out page {0}", file.Title));
                    } else {

                        mtr.TraceWarning(string.Format("The page {0}, {1} was allready checked out. Will not try to modify checkout status. This " +
                                                       "page will need to be checked in manually first if failing.", file.Title, file.Url));
                        page = null;
                    }
                }

                //Update the listviewxml of the webpart if a viewname is specified
                if (item.Attribute("WebPartType") != null && item.Attribute("WebPartType").Value == "XsltListViewWebPart") {
                    XsltListViewWebPart webPart = new XsltListViewWebPart();

                    XmlDocument xdoc = new XmlDocument();
                    xdoc.LoadXml(itemValue);

                    XmlNodeList nodes = xdoc.GetElementsByTagName("property");

                    //sett all the standard attributes on the web part
                    string listName = string.Empty;
                    if (nodes != null) {
                        foreach (XmlNode node in nodes) {

                            try {
                                string attribute = node.Attributes.GetNamedItem("name").Value;
                                string xmlText = node.InnerXml;
                                if (!string.IsNullOrEmpty(xmlText)) {
                                    object xValue = new object();
                                    string sType = webPart.GetType().GetProperty(attribute).PropertyType.UnderlyingSystemType.FullName;
                                    if (webPart.GetType().GetProperty(attribute).PropertyType.IsEnum) {
                                        xValue = Enum.Parse(webPart.GetType().GetProperty(attribute).PropertyType.UnderlyingSystemType, xmlText);
                                    } else {
                                        xValue = Convert.ChangeType(xmlText, Type.GetType(sType));
                                    }

                                    webPart.GetType().GetProperty(attribute).SetValue(webPart, xValue, null);
                                    if (attribute == "ListUrl")
                                        listName = (string)xValue;
                                }
                            } catch (Exception ex) {
                                mtr.TraceVerboseMessage(string.Format("XsltListViewWebPart unable to set property: " + node.Attributes.GetNamedItem("name").Value + " with value: " + node.InnerXml.ToString() + " Error message: " + ex.ToString()));
                            }
                        }

                        // we have a list and a view name. Get the view xml from the list and apply it to the web part.
                        listName = listName.Trim(' ', '/');
                        if (listName.Contains('/')) {
                            listName = listName.Split('/')[1];
                        }

                        SPList list = web.Lists[listName]; // ie. "Calendar" not "Lists/Calendar"

                        if (item.Attribute("ViewName") != null) {
                            string viewName = item.Attribute("ViewName").Value;
                            Guid viewGuid = list.Views[viewName].ID;
                            webPart.ViewGuid = viewGuid.ToString();
                        }
                        webPart.ListName = list.ID.ToString("B").ToUpper();

                        SPLimitedWebPartManager webPartManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared);
                        mtr.TraceVerboseMessage(string.Format("Adding webpart {0} to file {1}", webPart.Title, fileToGet));
                        webPartManager.AddWebPart(webPart, item.Attribute("WebPartZoneID").Value, webPartOrder);
                        //Checkin if publishingpage
                        if (page != null) {
                            page.CheckIn("Automatic checkin for upgrade.");
                            mtr.TraceVerboseMessage(string.Format("Checked in page {0} ", page.Title));
                        }
                        mtr.TraceVerboseMessage(string.Format("Webpart {0} added to file {1}", webPart.Title, fileToGet));
                        webPartManager.Web.Dispose();
                    }
                } else {
                    SPLimitedWebPartManager webPartManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared);
                    DNWebPart webPart = webPartManager.ImportWebPart(xmlTextReader, out errorMessage);
                    mtr.TraceVerboseMessage(string.Format("Adding webpart {0} to file {1}", webPart.Title, fileToGet));

                    //item.Attribute("WebPartType").Value == "XsltListViewWebPart"
                    //Her bør det inn en sjekk om det er en AllUsersWebpart slik at ikke httpcontexten blir opprettet alltid
                    bool contextCreated = false;
                    if (System.Web.HttpContext.Current == null) {
                        HttpRequest request = new HttpRequest("", web.Url, "");
                        HttpContext.Current = new HttpContext(request, new HttpResponse(new StringWriter()));
                        HttpContext.Current.Items["HttpHandlerSPWeb"] = web;
                        contextCreated = true;
                    }

                    webPartManager.AddWebPart(webPart, item.Attribute("WebPartZoneID").Value, webPartOrder);
                    //Checkin if publishingpage
                    if (page != null) {
                        page.CheckIn("Automatic checkin for upgrade.");
                        mtr.TraceVerboseMessage(string.Format("Checked in page {0} ", page.Title));
                    }
                    mtr.TraceVerboseMessage(string.Format("Added webpart {0} to file {1}", webPart.Title, fileToGet));
                    webPartManager.Web.Dispose();

                    //Close the context
                    if (contextCreated) {
                        HttpContext.Current = null;
                    }
                }

            } catch (Exception ex) {
                mtr.TraceError("Unable to add web parts", ex);
            }
        }
        private static string ReplaceTokens(SPWeb web, string itemvalue, XAttribute webpartType) {
            if (webpartType != null) {
                XmlDocument xdoc = new XmlDocument();
                xdoc.LoadXml(itemvalue);

                switch (webpartType.Value.ToLower()) {

                    case "siteusers":
                        //Set up xml namespaces for siteusers webpart
                        XmlNamespaceManager nsMgr = new XmlNamespaceManager(xdoc.NameTable);
                        nsMgr.AddNamespace("tns", "http://schemas.microsoft.com/WebPart/v2");
                        nsMgr.AddNamespace("tnm", "http://schemas.microsoft.com/WebPart/v2/Members");
                        nsMgr.AddNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
                        nsMgr.AddNamespace("xsd", "http://www.w3.org/2001/XMLSchema");

                        //select MembershipGroupId token (eg: %[sitetitle] Members%)
                        XmlNode selectedNode = xdoc.SelectSingleNode("/tns:WebPart/tnm:MembershipGroupId", nsMgr);

                        string grouptemp = selectedNode.InnerText;

                        //replace the sitetitle token with title from current web.
                        if (grouptemp.IndexOf("[sitetitle]") > 0) {
                            string title = web.Title;
                            if (!web.HasUniqueRoleAssignments) {
                                SPWeb pWeb = web;

                                while (!pWeb.HasUniqueRoleDefinitions) {
                                    pWeb = pWeb.ParentWeb;
                                }
                                title = pWeb.Title;
                                pWeb.Close();
                            }
                            grouptemp = grouptemp.Replace("[sitetitle]", title);
                        }
                        //find the sharepoint group and groupid in the sitecollection and getrid of the %
                        SPGroup membershipGroup = web.Groups[grouptemp.Replace("%", "")];
                        if (membershipGroup != null) {
                            //if exist replace the token with the membershipgroupId.
                            itemvalue = itemvalue.Replace(selectedNode.InnerText, membershipGroup.ID.ToString());
                        }
                        break;
                    case "xsltlistviewwebpart":
                        string propPath = "/webParts/tns:webPart/tns:data/tns:properties/tns:property[@name='{0}']";
                        XmlNamespaceManager nsMgrXlv = new XmlNamespaceManager(xdoc.NameTable);
                        nsMgrXlv.AddNamespace("tns", "http://schemas.microsoft.com/WebPart/v3");

                        try {
                            //Remove WebId
                            if (NodeExist(string.Format(propPath, "WebId"), xdoc, nsMgrXlv)) {
                                xdoc.SelectSingleNode(string.Format(propPath, "WebId"), nsMgrXlv).InnerText = "";
                            }
                        } catch (Exception ex) {
                            mtr.TraceVerboseMessage(TraceSeverity.Unexpected, string.Format("Could not find the WebId property in xsltlistviewwebpart."), ex);
                        }
                        try {
                            //Remove ListId
                            if (NodeExist(string.Format(propPath, "ListId"), xdoc, nsMgrXlv)) {
                                xdoc.SelectSingleNode(string.Format(propPath, "ListId"), nsMgrXlv).InnerText = "";
                            }
                        } catch (Exception ex) {
                            mtr.TraceVerboseMessage(TraceSeverity.Unexpected, string.Format("Could not find the ListId property in xsltlistviewwebpart."), ex);
                        }
                        try {
                            //Give titleurl a reference to the current web
                            string titleurl = xdoc.SelectSingleNode(string.Format(propPath, "TitleUrl"), nsMgrXlv).InnerText;

                            int ix = titleurl.LastIndexOf(titleurl.Contains("/Lists/") ? "/Lists/" : "/");

                            string sitetitle = titleurl.Substring(ix, titleurl.Length - ix);
                            string newurl = "~siteurl" + sitetitle;
                            xdoc.SelectSingleNode(string.Format(propPath, "TitleUrl"), nsMgrXlv).InnerText = newurl;
                        } catch (Exception ex) {
                            mtr.TraceVerboseMessage(TraceSeverity.Unexpected, string.Format("Could not find the TitleUrl property in xsltlistviewwebpart."), ex);
                        }
                        itemvalue = xdoc.OuterXml;
                        break;
                }
            }
            //replace the ~siteurl token in the webpart with the current siteurl
            itemvalue = itemvalue.Replace("~siteurl", web.Url);
            return itemvalue;
        }

        private static string getInheritedParentTitle(SPWeb web) {
            if (!web.HasUniqueRoleAssignments) {
                getInheritedParentTitle(web.ParentWeb);
            }

            return web.Title;
        }
        private static bool NodeExist(string xpath, XmlDocument xdoc, XmlNamespaceManager nsMgr) {
            XmlNode xn = xdoc.SelectSingleNode(xpath, nsMgr);
            if (xn != null) {
                return true;
            }
            return false;
        }

        //        <!-- Current events-->
        //<AllUsersWebPart WebPartZoneID="Left" WebPartOrder="4" FileName="sitepages/default.aspx" ViewName="Current Events">
        //  <![CDATA[               
        //  <webParts>
        //    <webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
        //      <metaData> 
        //        <type name="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart,Microsoft.SharePoint,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" />
        //        <importErrorMessage>Cannot import this Web Part.</importErrorMessage>
        //      </metaData>
        //      <data>    
        //        <properties>                               
        //        <property name="Title" type="string">Current events</property>
        //          <property name="AllowConnect" type="bool">False</property>                             
        //          <property name="ChromeType" type="chrometype">Default</property>
        //          <property name="AllowClose" type="bool">False</property>
        //          <property name="ListUrl" type="string" >Lists/Calendar </property>
        //          <property name="ViewId" type="int">2</property>
        //        </properties>
        //      </data>
        //    </webPart>
        //  </webParts>        
        //  ]]>
        //</AllUsersWebPart>
        public static void RenameWebPart(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting RenameWebPart()");
            if (item.Attribute("WebPartTitle") != null && item.Attribute("WebPartRenameTo") != null && item.Attribute("FileName") != null) {
                try {
                    string webPartTitle = item.Attribute("WebPartTitle").Value;
                    string webPartRenameTo = item.Attribute("WebPartRenameTo").Value;
                    string webPartPage = item.Attribute("FileName").Value;


                    SPLimitedWebPartManager webPartManager = web.GetLimitedWebPartManager(webPartPage, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
                    DNWebPart webpart;

                    for (int i = webPartManager.WebParts.Count - 1; i >= 0; i--) {
                        webpart = webPartManager.WebParts[i];

                        if (webpart.Title == webPartTitle) {
                            webpart.Title = webPartRenameTo;
                            webPartManager.SaveChanges(webpart);
                            web.Update();
                        }
                    }
                    webPartManager.Dispose();
                } catch (Exception ex) {
                    mtr.TraceError("Unable to rename web part.", ex);
                }
            }
        }
        public static void DeleteWebPart(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting DeleteWebPart()");
            if (item.Attribute("WebPartTitle") != null && item.Attribute("FileName") != null) {
                try {
                    string webPartTitle = item.Attribute("WebPartTitle").Value;
                    string webPartPage = item.Attribute("FileName").Value;

                    SPLimitedWebPartManager webPartManager = web.GetLimitedWebPartManager(webPartPage, System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared);
                    DNWebPart webpart;

                    for (int i = webPartManager.WebParts.Count - 1; i >= 0; i--) {
                        webpart = webPartManager.WebParts[i];

                        if (webpart.Title == webPartTitle) {
                            webPartManager.DeleteWebPart(webpart);
                            web.Update();
                        }
                    }
                } catch (Exception ex) {
                    mtr.TraceError("Unable to delete web part.", ex);
                }
            }
        }

        public static void DeleteWebParts(SPWeb web, string fileName) {
            mtr.TraceVerboseMessage("Starting DeleteWebParts()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (fileName == null) return;
            try {
                SPFile file = web.GetFile(fileName);
                SPLimitedWebPartManager webPartManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared);

                List<DNWebPart> webPartList = new List<DNWebPart>();

                foreach (DNWebPart webPart in webPartManager.WebParts) {
                    webPartList.Add(webPart);
                }

                foreach (DNWebPart webPart in webPartList) {
                    webPartManager.DeleteWebPart(webPart);
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to delete web parts", ex);
            }
        }

        public static void AddListViewWebPart(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting AddListViewWebParts()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;

            ListViewWebPartItem lViewItem = new ListViewWebPartItem(item.Attributes());

            //check if a custom filename is provided as target for the webpart or use the site's welcomepage as fallback

            string pageFileName = string.Empty;
            if (item.Attribute("FileName") != null) {

                if (web.GetFile(item.Attribute("FileName").Value).Exists) {
                    pageFileName = item.Attribute("FileName").Value;
                }
            } else if (web.GetFile(web.RootFolder.WelcomePage).Exists) {
                pageFileName = web.RootFolder.WelcomePage;
            } else {
                mtr.TraceVerboseMessage(string.Format("Unable to AddListViewWebParts(). There is no file present or provided to add the webparts to."));
                return;
            }

            string webPartTitle = string.Empty;

            try {
                mtr.TraceVerboseMessage(string.Format("Setting up ListViewWebPart : '{0}'", lViewItem.Title));
                ListViewWebPart webPart = new ListViewWebPart();
                webPart.Title = lViewItem.Title;
                if (!string.IsNullOrEmpty(lViewItem.TitleUrl)) webPart.TitleUrl = lViewItem.TitleUrl;
                webPart.AllowMinimize = bool.Parse(lViewItem.AllowMinimize);
                webPart.AllowClose = bool.Parse(lViewItem.AllowClose);
                webPart.AllowHide = bool.Parse(lViewItem.AllowHide);
                webPart.AllowZoneChange = bool.Parse(lViewItem.AllowZoneChange);
                webPart.AllowConnect = bool.Parse(lViewItem.AllowConnect);
                webPart.AllowEdit = bool.Parse(lViewItem.AllowEdit);

                string listName = lViewItem.ListName;
                string viewQuery = string.Empty;
                if (item.Element("ViewQuery") != null) {
                    viewQuery = item.Element("ViewQuery").Value;
                }
                string viewName = lViewItem.ViewName;
                string zoneID = lViewItem.ZoneID;
                string zoneIndex = lViewItem.ZoneIndex;

                mtr.TraceVerboseMessage(string.Format("Calling AddListViewWebPart with : '{0}'", lViewItem.Title));
                AddListViewWebPart(web, pageFileName, webPart, listName, viewName, zoneID, zoneIndex, viewQuery);

                if (lViewItem.ToolbarType == "NoToolbar") {
                    DisableToolbar(webPart, "None");
                } else if (lViewItem.ToolbarType == "Summary Toolbar") {
                    DisableToolbar(webPart, "Freeform");
                }
            } catch (Exception ex) {
                mtr.TraceError(string.Format("Unable to AddListViewWebParts()"), ex);
            }
        }
        private static void AddListViewWebPart(SPWeb web, string fileName, ListViewWebPart webPart, string listName, string viewName, string zoneID, string zoneIndex, string viewQuery) {
            mtr.TraceVerboseMessage(string.Format("Starting AddListViewWebPart() with parameters - fileName:{0}, listName:{1}, viewName:{2}.", fileName, listName, viewName));
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (fileName == null) throw new ArgumentNullException("webpart", "Cannot be null or no default root page found");
            if (webPart == null) throw new ArgumentNullException("webpart", "Cannot be null");
            if (listName == null) throw new ArgumentNullException("listname", "Cannot be null");
            if (viewName == null) throw new ArgumentNullException("viewname", "Cannot be null");
            if (zoneID == null) throw new ArgumentNullException("zoneid", "Cannot be null");
            if (zoneIndex == null) throw new ArgumentNullException("zoneindex", "Cannot be null");
            try {
                SPList list = web.Lists[listName];
                webPart.ListName = list.ID.ToString("B").ToUpper();
                if (!string.IsNullOrEmpty(viewName)) {
                    SPView view = list.Views[viewName];
                    mtr.TraceVerboseMessage(string.Format("Fetched view for the listview webpart : '{0}'", viewName));
                    if (!string.IsNullOrEmpty(viewQuery)) {
                        mtr.TraceVerboseMessage(string.Format("Setting the viewquery to  : '{0}'", viewQuery));
                        view.Query = viewQuery;
                    }
                    mtr.TraceVerboseMessage(string.Format("Setting the listviewXML to  : '{0}'", view.GetViewXml()));
                    webPart.ListViewXml = view.GetViewXml();
                }
                mtr.TraceVerboseMessage(string.Format("Getting the webpartmanager and adding webpart : '{0}'", webPart.Title));
                SPFile file = web.GetFile(fileName);
                SPLimitedWebPartManager webPartManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared);
                webPartManager.AddWebPart(webPart, zoneID, int.Parse(zoneIndex));
                //webPartManager.Web.Dispose();
            } catch (Exception ex) {
                mtr.TraceError(string.Format("Unable to add web part {0}", webPart.Title), ex);
            }
        }


        public static void AddWebPartConnectionsV3(SPWeb web, string fileName) {
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (fileName == null) return;
            try {
                SPLimitedWebPartManager webPartManager = web.GetLimitedWebPartManager(fileName, PersonalizationScope.Shared);

                DNWebPart providerWebPart = webPartManager.WebParts["Documents 1"];
                DNWebPart consumerWebPart = webPartManager.WebParts["Documents 2"];

                foreach (DNWebPart webPart in webPartManager.WebParts) {
                    if (webPart.Title == "Documents 1")
                        providerWebPart = webPart;
                    else if (webPart.Title == "Documents 2")
                        consumerWebPart = webPart;
                }

                ProviderConnectionPointCollection providerConnectionPointCollection = webPartManager.GetProviderConnectionPoints(consumerWebPart);
                ConsumerConnectionPointCollection consumerConnectionPointCollection = webPartManager.GetConsumerConnectionPoints(providerWebPart);
                ProviderConnectionPoint providerConnectionPoint = webPartManager.GetProviderConnectionPoints(consumerWebPart)["ListViewRowProvider_WPQ_"];
                ConsumerConnectionPoint consumerConnectionPoint = webPartManager.GetConsumerConnectionPoints(providerWebPart)["ListViewFilterConsumer_WPQ_"];

                webPartManager.SPConnectWebParts(providerWebPart, providerConnectionPoint, consumerWebPart, consumerConnectionPoint);
            } catch (Exception ex) {
                mtr.TraceError("Unable to AddWebPartConnections()", ex);
            }
        }

        public static void AddWebPartConnectionsV2(SPWeb web, string fileName, string siteName, XElement siteConfigurations) {
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (siteName == null) throw new ArgumentNullException("siteName", "Cannot be null");
            if (siteConfigurations == null) return;
            mtr.TraceVerboseMessage("Starting AddWebPartConnections2()");
            try {
                var items =
                    from s in siteConfigurations.Elements("SiteConfiguration")
                    where s.Attribute("Name").Value == siteName
                    from q in s.Elements("WebPartConnection2")
                    select new {
                        Provider = q.Attribute("Provider").Value,
                        Consumer = q.Attribute("Consumer").Value,
                        ConnectionID = q.Attribute("ConnectionID").Value
                    };

                SPLimitedWebPartManager webPartManager = web.GetLimitedWebPartManager(fileName, PersonalizationScope.Shared);

                foreach (var item in items) {
                    mtr.TraceVerboseMessage(string.Format("Connecting provider \"{0}\" to consumer\"{1}\"", item.Provider, item.Consumer));

                    SPWebPart providerWebPart = FindWebPartByTitle(webPartManager, item.Provider);
                    SPWebPart consumerWebPart = FindWebPartByTitle(webPartManager, item.Consumer);

                    if (providerWebPart.ConnectionID == Guid.Empty)
                        providerWebPart.ConnectionID = Guid.NewGuid();
                    if (consumerWebPart.ConnectionID == Guid.Empty)
                        consumerWebPart.ConnectionID = Guid.NewGuid();

                    consumerWebPart.Connections = consumerWebPart.ConnectionID + "," +
                         providerWebPart.ConnectionID + "," + item.ConnectionID;

                    webPartManager.SaveChanges(providerWebPart);
                    webPartManager.SaveChanges(consumerWebPart);
                }
            } catch (Exception ex) {
                mtr.TraceError("Unable to connect web parts", ex);
            }
        }


        public static void UpdatePropertyBag(SPWeb web, XElement item, XElement overridesection) {
            mtr.TraceVerboseMessage("Starting UpdatePropertyBag()");
            try {
                string name = item.Attribute("Name").Value;
                string value = item.Attribute("Value").Value;

                bool allowOverride = false;
                if (!(item.Attribute("AllowWebConfigOverride") == null)) allowOverride = bool.Parse(item.Attribute("AllowWebConfigOverride").Value);
                if (allowOverride) {
                    try {

                        // Get the override value from the overrideconfiguration
                        var newValue =
                        from s in overridesection.Elements("PropertyBag")
                        where s.Attribute("Name").Value == name
                        select s.Attribute("Value").Value;
                        value = newValue.FirstOrDefault();
                    } catch (Exception ex) {
                        mtr.TraceError("Could not find override key in web.config", ex);
                    }

                }
                if (web.Properties.ContainsKey(name)) {
                    web.Properties[name] = value;
                    mtr.TraceVerboseMessage(string.Format("UpdatePropertyBag() updated property: {0} with value: {1} and overridesetting set to {2}", name, value, allowOverride));
                } else {
                    web.Properties.Add(name, value);
                    mtr.TraceVerboseMessage(string.Format("UpdatePropertyBag() added property: {0} with value: {1} and overridesetting set to {2}", name, value, allowOverride));
                }

                web.Properties.Update();
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to UpdatePropertyBag", ex);
            }
        }

        public static void RemovePropertyBag(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting RemovePropertyBag()");
            try {
                string name = Convert.ToString(item.Name);
                string value = Convert.ToString(item.Value);
                if (web.Properties.ContainsKey(name)) {
                    web.Properties.Remove(name);
                }
                web.Properties.Update();
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError(string.Format("Unable to remove PropertBagValue with name {0} and value {1} ", item.Name, item.Value), ex);
            }
        }

        public static void UpdateAllPropertyBagItem(SPWeb web, XElement item, XElement overridesection) {
            mtr.TraceVerboseMessage("Starting UpdateAllPropertyBagItem()");

            try {
                string name = item.Attribute("Name").Value;
                string value = item.Attribute("Value").Value;

                bool allowOverride = false;
                if (item.Attribute("AllowWebConfigOverride") != null)
                    allowOverride = bool.Parse(item.Attribute("AllowWebConfigOverride").Value);
                if (allowOverride) {
                    try {

                        // Get the override value from the overrideconfiguration
                        var newValue =
                            from s in overridesection.Elements("AllPropertyBagItem")
                            where s.Attribute("Name").Value == name
                            select s.Attribute("Value").Value;
                        value = newValue.FirstOrDefault();
                    } catch (Exception ex) {
                        mtr.TraceError("Could not find override key in web.config", ex);
                    }

                }
                if (web.AllProperties.ContainsKey(name)) {
                    web.AllProperties[name] = value;
                    mtr.TraceVerboseMessage(
                        string.Format(
                            "UpdateAllPropertyBagItem() updated property: {0} with value: {1} and overridesetting set to {2}",
                            name, value, allowOverride));
                } else {
                    web.AllProperties.Add(name, value);
                    mtr.TraceVerboseMessage(
                        string.Format(
                            "UpdateAllPropertyBagItem() added property: {0} with value: {1} and overridesetting set to {2}",
                            name, value, allowOverride));
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to UpdateAllPropertyBagItem", ex);
            }
        }

        public static void RemoveAllPropertyBagItem(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting RemoveAllPropertyBagItem()");
            try {
                string name = Convert.ToString(item.Name);
                string value = Convert.ToString(item.Value);
                if (web.AllProperties.ContainsKey(name)) {
                    web.AllProperties.Remove(name);
                    //web.Properties[name] = null;
                }
                web.Update();
                //web.Properties.Update();
            } catch (Exception ex) {
                mtr.TraceError(string.Format("Unable to remove PropertBagValue with name {0} and value {1} ", item.Name, item.Value), ex);
            }
        }

        public static void CreateList(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting CreateLists()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            try {
                string title = item.Attribute("Title").Value;
                mtr.TraceVerboseMessage("Creating list with title = " + title);
                string type = string.Empty;
                string description = string.Empty;
                bool enableAttachments = false;
                bool isCustomListTemplate = false;


                if (item.Attribute("Type") != null) {
                    type = item.Attribute("Type").Value;
                }
                if (item.Attribute("Description") != null) {
                    description = item.Attribute("Description").Value;
                }
                if (item.Attribute("EnableAttachments") != null) {
                    enableAttachments = bool.Parse(item.Attribute("EnableAttachments").Value);
                }
                if (item.Attribute("IsCustomListTemplate") != null) {
                    isCustomListTemplate = bool.Parse(item.Attribute("IsCustomListTemplate").Value);
                }

                // Guid listGuid = new Guid();
                SPListTemplate template;
                mtr.TraceVerboseMessage(string.Format("Adding list {0}", title));

                if (isCustomListTemplate) {
                    SPListTemplateCollection templateList = web.Site.GetCustomListTemplates(web);
                    template = templateList[type];
                    //listGuid = web.Lists.Add(title, description, template);    
                } else {
                    //mtr.TraceVerboseMessage(string.Format("Adding list {0}", title));
                    template = web.ListTemplates[type];
                }
                Guid listGuid = web.Lists.Add(title, description, template);

                SPList list = web.Lists[listGuid];
                list.EnableAttachments = enableAttachments;




                // Versioning
                if (item.Attribute("EnableVersioning") != null) {
                    list.EnableVersioning = bool.Parse(item.Attribute("EnableVersioning").Value);
                    if (item.Attribute("MajorVersionLimit") != null) {
                        list.MajorVersionLimit = int.Parse(item.Attribute("MajorVersionLimit").Value);
                    }
                    if (item.Attribute("MajorWithMinorVersionsLimit") != null) {
                        list.EnableMinorVersions = true;
                        list.MajorWithMinorVersionsLimit = int.Parse(item.Attribute("MajorWithMinorVersionsLimit").Value);
                    }
                }


                //Workflows                        
                SPList taskList = null;
                SPList historyList = null;

                if ((item.Descendants("{http://tempuri.org/siteconfigurator.xsd}WorkFlow").Count() > 0) && (web.ListExists("Tasks")) && (web.ListExists("Workflow History"))) {
                    taskList = web.Lists["Tasks"];
                    historyList = web.Lists["Workflow History"];

                    //Remove existing (OOB) assosciations (we are creating a new list...)
                    foreach (Microsoft.SharePoint.Workflow.SPWorkflowAssociation association in list.WorkflowAssociations) {
                        list.RemoveWorkflowAssociation(association);
                    }
                    list.Update();

                    Microsoft.SharePoint.Workflow.SPWorkflowTemplate _template = null;

                    foreach (XElement element in item.Descendants("{http://tempuri.org/siteconfigurator.xsd}WorkFlow")) {
                        foreach (Microsoft.SharePoint.Workflow.SPWorkflowTemplate wtemplate in web.WorkflowTemplates) {
                            if (wtemplate.Name == element.Attribute("Title").Value) {
                                _template = wtemplate;
                                Microsoft.SharePoint.Workflow.SPWorkflowAssociation asso =
                                    Microsoft.SharePoint.Workflow.SPWorkflowAssociation.CreateListAssociation(_template, _template.Name, taskList, historyList);
                                list.AddWorkflowAssociation(asso);
                            }
                        }
                    }
                } else {
                    if (item.Descendants("{http://tempuri.org/siteconfigurator.xsd}WorkFlow").Count() == 0) mtr.TraceVerboseMessage("There are no workflows defined");
                    else {
                        if (!web.ListExists("Tasks")) mtr.TraceVerboseMessage("There is no task list defined. (It must be created before adding workflows.)");
                        if (!web.ListExists("Workflow History")) mtr.TraceVerboseMessage("There is no Workflow History list defined. (It must be created before adding workflows.)");
                    }
                }

                // Update list, in case of error in content type configuration
                list.Update();

                // Content types
                IEnumerable<XElement> contentTypes = item.Descendants("{http://tempuri.org/siteconfigurator.xsd}ContentType");

                if (contentTypes != null && contentTypes.Count() > 0) {
                    // Enable management of content types
                    list.ContentTypesEnabled = true;

                    //Remove all existing content types, except one (not allowed to delete all)
                    for (int i = list.ContentTypes.Count; i > 1; i--) {
                        list.ContentTypes.Delete(list.ContentTypes[i - 1].Id);
                    }

                    // Keep id of the content type that was not deleted
                    SPContentTypeId remainingContentTypeId = list.ContentTypes[0].Id;

                    // Add all defined content types
                    foreach (XElement element in contentTypes) {
                        string contentTypeId = element.Attribute("Id").Value;

                        if (contentTypeId != null && contentTypeId != string.Empty) {
                            SPContentType ct = web.ContentTypes[new SPContentTypeId(contentTypeId)];
                            if (ct != null) {
                                // If the one content type that was not deleted is supposed to be in the list
                                if (ct.Id.IsParentOf(remainingContentTypeId)) {
                                    remainingContentTypeId = SPContentTypeId.Empty;
                                    mtr.TraceVerboseMessage("Keeping the last CT on the list, not updating.");
                                } else list.ContentTypes.Add(ct);
                            } else {
                                mtr.TraceVerboseMessage("Unable to add content type with id = " + contentTypeId + ", not found in site");
                            }
                        }
                    }

                    // Delete the one content type that was not deleted, unless marked as available
                    if (remainingContentTypeId != SPContentTypeId.Empty) {
                        list.ContentTypes.Delete(remainingContentTypeId);
                    }
                } else {
                    mtr.TraceVerboseMessage("There are no content types defined");
                }
                // DisableCreateNewDocuments
                if (item.Attribute("DisableDocumentCreation") != null) {
                    if (item.Attribute("DisableDocumentCreation").Value.ToLower() == "true") {
                        // Enable management of content types
                        list.ContentTypesEnabled = true;
                        list.Update();
                        //Remove all existing content types, except one (not allowed to delete all)
                        for (int i = list.ContentTypes.Count; i > 0; i--) {
                            // Do not remove the folder content type
                            if (!list.ContentTypes[i - 1].Name.ToString().Equals("Folder")) list.ContentTypes.Delete(list.ContentTypes[i - 1].Id);
                        }
                    }
                }
                // DisableCreateNewFolder
                if (item.Attribute("EnableFolderCreation") != null) {
                    list.EnableFolderCreation = bool.Parse(item.Attribute("EnableFolderCreation").Value);
                }

                list.Update();
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to create list " + item.Attribute("Title").Value, ex);
            }
        }
        public static void CreateViews(SPWeb web, XElement item) {
            string title = item.Attribute("ListTitle").Value;
            if (web.ListExists(title)) {
                SPList list = web.Lists[title];
                CreateListViews(list, item);
            } else {
                mtr.TraceWarning("Could not find list " + item.Attribute("ListTitle").Value);
            }
        }
        private static void CreateListViews(SPList list, XElement item) {
            string itemValue = item.Value;
            if (!string.IsNullOrEmpty(itemValue)) {
                XmlDocument xdoc = new XmlDocument();
                xdoc.LoadXml(itemValue);

                XmlNodeList xnl = xdoc.DocumentElement.SelectNodes("/Views/View");
                if (xnl != null) {
                    System.Collections.Specialized.StringCollection strColl;

                    foreach (XmlNode xn in xnl) {
                        try {
                            strColl = new System.Collections.Specialized.StringCollection();
                            XmlNode viewFields = xn.SelectSingleNode("ViewFields");
                            foreach (XmlNode viewField in viewFields.ChildNodes) {
                                strColl.Add(viewField.Attributes["Name"].Value);
                            }
                            string query = xn.SelectSingleNode("Query").InnerXml;
                            string viewname = xn.Attributes["DisplayName"].Value;
                            XmlNode rowlimitNode = xn.SelectSingleNode("RowLimit");

                            list.Views.Add(viewname, strColl, query, Convert.ToUInt32(rowlimitNode.InnerText), Convert.ToBoolean(rowlimitNode.Attributes["Paged"].Value), false);

                            if (xn.Attributes["Scope"] != null) {
                                SPView view = list.Views[viewname];
                                switch (xn.Attributes["Scope"].Value) {
                                    case "Recursive":
                                        view.Scope = SPViewScope.Recursive;
                                        break;
                                    case "FilesOnly":
                                        view.Scope = SPViewScope.FilesOnly;
                                        break;
                                    case "RecursiveAll":
                                        view.Scope = SPViewScope.RecursiveAll;
                                        break;
                                    case "Default":
                                        view.Scope = SPViewScope.Default;
                                        break;
                                }

                                view.Update();
                            }
                        } catch (Exception ex) {
                            mtr.TraceError("Unable to create view " + xn.Attributes["DisplayName"].Value, ex);
                        }
                    }
                    list.Update();
                }
            }
        }

        //Creates custom fields on SPLists
        //Expects CustomFields, CustomField, and Field nodes as part of a CDATA entry under CustomListField node in configuration
        internal static void CreateCustomListFields(SPWeb web, XElement item) {
            //return if item has no value
            string itemValue = item.Value;
            if (string.IsNullOrEmpty(itemValue)) return;

            XmlDocument xdoc = new XmlDocument();
            xdoc.LoadXml(itemValue);

            //return if list does not exist
            string listTitle = item.Attribute("ListTitle").Value;
            if (!web.ListExists(listTitle)) return;

            SPList list = web.Lists[listTitle];

            //Get all CustomField nodes
            XmlNodeList xnl = xdoc.DocumentElement.SelectNodes("/CustomFields/CustomField");

            //return if xnl har no customFields
            if (xnl == null) return;

            foreach (XmlNode xn in xnl) {
                try {
                    //get manually set internal and display names
                    string internalName = xn.Attributes["InternalName"].Value;
                    string name = xn.Attributes["Name"].Value;

                    XmlNode field = xn.SelectSingleNode("Field");
                    //set displayName to be internal name on creation
                    field.Attributes["DisplayName"].Value = internalName;

                    if (field.Attributes["Type"].Value == "Lookup") {
                        SPList lookupList = web.Lists[xn.Attributes["LookupList"].Value];

                        list.Fields.AddLookup(field.Attributes["DisplayName"].Value, lookupList.ID,
                                              bool.Parse(field.Attributes["Required"].Value));
                        list.Update();
                    } else {
                        string fieldXml = field.OuterXml;
                        //add new field to SPList
                        list.Fields.AddFieldAsXml(fieldXml);
                    }
                    list.Update();

                    SPField newField = list.Fields[internalName];
                    //rename display name to a more appropriate name than internalName
                    newField.Title = name;
                    newField.Update();
                    list.Update();
                } catch (Exception ex) {
                    mtr.TraceError("Unable to create list field " + xn.Attributes["Name"].Value, ex);
                }
            }
        }

        public static void DeleteList(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting DeleteLists()");
            try {
                mtr.TraceVerboseMessage("Deleting list with title = " + item.Attribute("Title").Value);
                SPList list = web.Lists[item.Attribute("Title").Value];
                Guid listGuid = list.ID;
                if (!listGuid.Equals(Guid.Empty)) {
                    web.Lists.Delete(listGuid);
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to delete list " + item.Attribute("Title").Value, ex);
            }
        }

        public static void ActivateSiteCollectionFeature(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting ActivateSiteCollectionFeatures()");
            try {
                if (web.IsRootWeb == false) {
                    mtr.TraceVerboseMessage("This web is a subweb, exiting method. Only activating SiteCollectionfeatures if RootWeb.");
                    return;
                }
                Guid guid = new Guid(item.Attribute("Guid").Value);
                string featureScope = "None";
                if (item.Attribute("Scope") != null) {
                    featureScope = item.Attribute("Scope").Value.ToLower();
                }

                mtr.TraceVerboseMessage(string.Format("Activating site feature with guid: {0} - Scope:", guid, featureScope));
                using (SPSite spSite = web.Site) {

                    if (featureScope == "site") {
                        spSite.Features.Add(guid, true, SPFeatureDefinitionScope.Site);
                    }
                    else if (featureScope == "farm"){
                        spSite.Features.Add(guid, true, SPFeatureDefinitionScope.Farm);
                    }
                    else{
                        spSite.Features.Add(guid, true);
                    }
                }
                //web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to activate SiteCollectionFeature with GUID: " + item.Attribute("Guid").Value, ex);
            } finally {
                //web.Update();
            }
        }

        public static void DeactivateSiteCollectionFeatures(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting DeactivateSiteCollectionFeatures()");
            try {
                Guid guid = new Guid(item.Attribute("Guid").Value);
                mtr.TraceVerboseMessage(string.Format("Deactivating site feature with guid: {0}", guid));
                web.Site.Features.Remove(guid, true);
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to deactivate SiteCollectionFeature with GUID: " + item.Attribute("Guid").Value, ex);

            }
        }


        public static void ActivateWebFeature(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting ActivateWebFeatures()");
            try {
                Guid guid = new Guid(item.Attribute("Guid").Value);
                mtr.TraceVerboseMessage(string.Format("Activating web feature with guid: {0} ", guid));
                web.Features.Add(guid, true);
                //web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to activate webFeature with GUID: " + item.Attribute("Guid").Value, ex);
            } finally {
                //web.Update();
            }
        }

        public static void DeactivateWebFeatures(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting DeactivateWebFeatures()");
            try {
                Guid guid = new Guid(item.Attribute("Guid").Value);
                mtr.TraceVerboseMessage(string.Format("Deactivating web feature with guid: {0}", guid));
                web.Features.Remove(guid, true);
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to deactivate webFeature with GUID: " + item.Attribute("Guid").Value, ex);

            }
        }


        public static void ProvisionFile(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting ProvisionFiles()");
            string fileName = string.Empty;
            try {

                if (item.Attribute("FileName") != null) {
                    fileName = item.Attribute("FileName").Value;
                    string folderName = string.Empty;
                    string srcUrl = string.Empty;
                    string destUrl = string.Empty;
                    if (item.Attribute("Folder") != null) //item go to a subfolder
                    {
                        folderName = item.Attribute("Folder").Value;
                        srcUrl = SPUtility.GetGenericSetupPath("") + @"template\SiteTemplates\" + web.WebTemplate + @"\"
                                        + folderName + @"\" + fileName;
                        if (folderName.Contains(@"'\'")) folderName = folderName.Replace(@"'\'", "/");
                        destUrl = web.Url + "/" + folderName + "/" + fileName;
                    } else // item go to root level
                    {
                        srcUrl = SPUtility.GetGenericSetupPath("") + @"template\SiteTemplates\" + web.WebTemplate + @"\"
                                + fileName;
                        destUrl = web.Url + "/" + fileName;
                    }

                    mtr.TraceVerboseMessage(string.Format("Uploading from file :'{0}' to destination :'{1}'", srcUrl, destUrl));

                    UploadFile(srcUrl, destUrl);
                    // set welcome page if flag is set to true
                    if (item.Attribute("NavBarHome") != null) {
                        if (bool.Parse(item.Attribute("NavBarHome").Value)) {
                            SetWelcomePage(web, fileName, folderName);
                        }
                    }
                }
            } catch (Exception ex) {
                mtr.TraceError("Unable to Provision file with name: " + fileName, ex);
            }

        }

        private static void SetWelcomePage(SPWeb web, string fileName, string folder) {
            if (PublishingWeb.IsPublishingWeb(web)) {
                PublishingWeb pw = PublishingWeb.GetPublishingWeb(web);
                PublishingSite site = new PublishingSite(web.Site);
                pw.DefaultPage = web.GetFile(folder + "/" + fileName);
                pw.Update();
            } else {
                SPFolder rootFolder = web.RootFolder;
                if (!string.IsNullOrEmpty(folder)) rootFolder.WelcomePage = folder + "/" + fileName;
                else rootFolder.WelcomePage = fileName;
                rootFolder.Update();

            }
        }

        public static string UnprovisionFiles(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting UnprovisionFiles()");
            string defaultPageName = string.Empty;
            try {
                string destUrl = web.Url + "/" + item.Attribute("FileName").Value;
                web.Files.Delete(destUrl);
                if (bool.Parse(item.Attribute("NavBarHome").Value) == true) {
                    defaultPageName = Convert.ToString(item.Attribute("FileName").Value);
                }
            } catch (Exception ex) {
                mtr.TraceError("Unable to unprovision file with name: " + item.Attribute("FileName").Value, ex);
            }
            return defaultPageName;
        }
        public static void UploadFile(string srcUrl, string destUrl) {
            if (srcUrl == null) throw new ArgumentNullException("srcUrl", "Cannot be null");
            if (destUrl == null) throw new ArgumentNullException("destUrl", "Cannot be null");
            try {
                if (!File.Exists(srcUrl)) {
                    mtr.TraceVerboseMessage(String.Format("{0} does not exist", srcUrl));
                }

                using (SPSite siteCol = new SPSite(destUrl)) {
                    using (SPWeb site = siteCol.OpenWeb()) {
                        FileStream fStream = File.OpenRead(srcUrl);
                        byte[] contents = new byte[fStream.Length];
                        fStream.Read(contents, 0, (int)fStream.Length);
                        fStream.Close();

                        EnsureParentFolder(site, destUrl);
                        if (!site.GetFile(destUrl).Exists) site.Files.Add(destUrl, contents);
                        //else traceVerboseMessage(string.Format("The file '{0}' already exists, skipping upload of this file.", destUrl));
                    }
                }
            } catch (Exception ex) {
                mtr.TraceError(string.Format("Unable to UploadFile() with srcUrl={0} and destUrl={1}", srcUrl, destUrl), ex);
            }
        }
        public static string EnsureParentFolder(SPWeb parentSite, string destinUrl) {
            if (parentSite == null) throw new ArgumentNullException("parentsite", "Cannot be null");
            if (destinUrl == null) throw new ArgumentNullException("destinurl", "Cannot be null");
            try {
                destinUrl = parentSite.GetFile(destinUrl).Url;

                int index = destinUrl.LastIndexOf("/");
                string parentFolderUrl = string.Empty;

                if (index > -1) {
                    parentFolderUrl = destinUrl.Substring(0, index);

                    SPFolder parentFolder
                        = parentSite.GetFolder(parentFolderUrl);

                    if (!parentFolder.Exists) {
                        SPFolder currentFolder = parentSite.RootFolder;

                        foreach (string folder in parentFolderUrl.Split('/')) {
                            currentFolder
                                = currentFolder.SubFolders.Add(folder);
                        }
                    }
                }
                return parentFolderUrl;
            } catch (Exception ex) {
                mtr.TraceError(string.Format("Unable to EnsureParentFolder() on parentSite={0} and destinUrl={1}", parentSite, destinUrl), ex);
                return string.Empty;
            }
        }

        protected static SPWebPart FindWebPartByTitle(SPLimitedWebPartManager webPartManager, string title) {
            if (webPartManager == null) throw new ArgumentNullException("webpartmanager", "Cannot be null");
            if (title == null) throw new ArgumentNullException("title", "Cannot be null");
            SPWebPart foundWebPart = null;

            foreach (SPWebPart webPart in webPartManager.WebParts) {
                if (webPart.Title == title) {
                    foundWebPart = webPart;
                    break;
                }
            }
            return foundWebPart;
        }

        protected static void UpdateNodeProperty(SPNavigationNode node, string propertyName, object value) {
            if (node == null) throw new ArgumentNullException("web", "Cannot be null");
            if (propertyName == null) throw new ArgumentNullException("propertyname", "Cannot be null");
            if (value == null) throw new ArgumentNullException("value", "Cannot be null");


            if (node.Properties.Contains(propertyName))
                node.Properties.Remove(propertyName);
            node.Properties.Add(propertyName, value);
            node.Update();
        }

        protected static SPNavigationNode GetNodeByTitle(SPNavigationNodeCollection nodes, string title) {
            if (nodes == null) throw new ArgumentNullException("nodes", "Cannot be null");
            if (title == null) throw new ArgumentNullException("title", "Cannot be null");
            foreach (SPNavigationNode node in nodes) {
                if (node.Title.Equals(title))
                    return node;
            }
            return null;
        }

        protected static string GetUrlParameters(string link) {
            mtr.TraceVerboseMessage("Starting GetUrlParameters()");
            if (link == null) throw new ArgumentNullException("link", "Cannot be null");

            string parameters = string.Empty;
            try {
                int parameterPos = link.IndexOf("?");

                if (parameterPos > 0) {
                    parameters = link.Substring(parameterPos + 1);
                }
            } catch (Exception ex) {
                mtr.TraceError("Error getting GetUrlParameters()", ex);
            }
            return parameters;
        }

        private static void DisableToolbar(ListViewWebPart lvwp, string toolbarType) {
            mtr.TraceVerboseMessage("Starting DisableToolbar()");
            if (lvwp == null) throw new ArgumentNullException("lv", "Cannot be null");
            if (toolbarType == null) throw new ArgumentNullException("attribValue", "Cannot be null");
            try {
                // Get the SPView object that controls what the web part displays    
                PropertyInfo props = lvwp.GetType().GetProperty("View", BindingFlags.NonPublic | BindingFlags.Instance);
                SPView webpartView = props.GetValue(lvwp, null) as SPView;
                // This line is required to ensure that all the appropriate internal nodes of the SPView are populated  
                String temp = webpartView.SchemaXml;
                // Get the internal XML for the view so we can edit it    
                PropertyInfo nodeProp = webpartView.GetType().GetProperty("Node", BindingFlags.NonPublic | BindingFlags.Instance);
                XmlNode node = nodeProp.GetValue(webpartView, null) as XmlNode;
                // Now get the Toolbar node from the view so we can update its type property   
                XmlNode toolbarNode = node.SelectSingleNode("Toolbar");
                if (toolbarNode != null) {
                    switch (toolbarType) {
                        case "Standard":
                            break;
                        case "FreeForm":
                            toolbarNode.Attributes["Type"].Value = "FreeForm";
                            string newItemString = string.Empty;

                            XmlAttribute pos = toolbarNode.OwnerDocument.CreateAttribute("Position");
                            pos.Value = pos.Value = "After";
                            toolbarNode.Attributes.Append(pos);
                            switch (webpartView.ParentList.BaseTemplate) {
                                case SPListTemplateType.DiscussionBoard:
                                    newItemString = "discussion";
                                    break;
                                case SPListTemplateType.Links:
                                    newItemString = "link";
                                    break;
                                case SPListTemplateType.Tasks:
                                    newItemString = "task";
                                    break;
                                case SPListTemplateType.DocumentLibrary:
                                    newItemString = "document";
                                    break;
                                case SPListTemplateType.Announcements:
                                    newItemString = "announcement";
                                    break;
                                case SPListTemplateType.GenericList:
                                default:
                                    newItemString = "item";
                                    break;
                            }
                            toolbarNode.InnerXml = @"<IfHasRights><RightsChoices><RightsGroup PermAddListItems=""required"" /></RightsChoices><Then><HTML><![CDATA[ <table width=100% cellpadding=0 cellspacing=0 border=0 > <tr> <td colspan=""2"" class=""ms-partline""><IMG src=""/_layouts/images/blank.gif"" width=1 height=1 alt=""""></td> </tr> <tr> <td class=""ms-addnew"" style=""padding-bottom: 3px""> <img src=""/_layouts/images/rect.gif"" alt="""">&nbsp;<a class=""ms-addnew"" ID=""idAddNewItem"" href=""]]></HTML><URL Cmd=""New"" /><HTML><![CDATA["" ONCLICK=""javascript:NewItem(']]></HTML><URL Cmd=""New"" /><HTML><![CDATA[', truejavascript:return false;"" target=""_self"">]]></HTML><HTML>Add a new " + newItemString + @"</HTML><HTML><![CDATA[</a> </td> </tr> <tr><td><IMG src=""/_layouts/images/blank.gif"" width=1 height=5 alt=""""></td></tr> </table>]]></HTML></Then></IfHasRights>";
                            break;
                        case "None":
                            toolbarNode.Attributes["Type"].Value = "None";
                            break;
                    }
                    webpartView.Update();
                }
            } catch (Exception ex) {
                mtr.TraceError(string.Format("Unable to DisableToolbar()"), ex);
            }
        }

        /// <summary>
        /// Apply theme to a web 
        /// To be used with the 2007 themes
        /// </summary>
        /// <param name="web">Web</param>
        /// <param name="themeName">Name (Id) of theme</param>
        public static bool ApplyTheme(SPWeb web, XElement item) {
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) throw new ArgumentNullException("item", "Cannot be null");
            bool success = false;
            try {
                string themeName = item.Attribute("Id").Value;
                mtr.TraceVerboseMessage("Applying theme " + themeName);
                if (!string.IsNullOrEmpty(themeName)) {
                    web.ApplyTheme(themeName);
                    success = true;
                } else {
                    mtr.TraceVerboseMessage("Theme name is null or empty.");
                }
            } catch (Exception ex) {
                mtr.TraceError(string.Format("Unable to ApplyTheme(web, {0})", item.Attribute("Id").Value), ex);
                success = false;
            }
            return success;
        }



        /// <summary>
        /// Apply theme to a web
        /// To be used with the 2010 Themes
        /// </summary>
        /// <param name="web">Web</param>
        /// <param name="themeName">Name (Id) of theme</param>
        [Conditional("SP2010")]
        public static void ApplyTheme2010(SPSite site, XElement item) {
#if SP2010
            if (site == null) throw new ArgumentNullException("site", "Cannot be null");
            if (item == null) throw new ArgumentNullException("item", "Cannot be null");
            try {
                string themeName = item.Attribute("Id").Value;
                mtr.TraceVerboseMessage("ApplyTheme2010: Applying theme " + themeName);
                if (!string.IsNullOrEmpty(themeName)) {
                    using (SPWeb web = site.OpenWeb()) {
                        ThmxTheme theme = ThmxTheme.Open(site, "/_catalogs/theme/" + themeName + ".thmx");
                        theme.ApplyTo(web, false);
                        try {
                            web.Update();
                        } catch (Exception e) {
                            mtr.TraceError(string.Format("Unable to ApplyTheme2010(web, {0})", themeName), e);
                        }
                    }
                } else {
                    mtr.TraceVerboseMessage("ApplyTheme2010: Theme name is null or empty.");
                }
            } catch (Exception ex) {
                mtr.TraceError(string.Format("Unable to ApplyTheme(web, {0})", item.Attribute("Id").Value), ex);
            }
#endif
        }


        public static bool ApplyIrmSetting(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting ApplyIrmSettings");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return false;

            mtr.TraceVerboseMessage("Starting ApplyIrmSettings() for web " + web.Url);
            SPWebService svc = SPFarm.Local.Services.GetValue<SPWebService>();
            SPIrmSettings irmSettings = svc.IrmSettings;
            mtr.TraceVerboseMessage("Checking global irm-settings for farm..");
            if (irmSettings == null) {
                mtr.TraceVerboseMessage("Irm-settings not found for farm. Aborting.");
                return false;
            }
            try {
                IrmSettingsItem irmItem = new IrmSettingsItem(item.Attribute("ListInstance").Value, System.Convert.ToBoolean(item.Attribute("IrmEnabled").Value), item.Attribute("IrmTitle").Value, item.Attribute("IrmDescription").Value,
                   System.Convert.ToBoolean(item.Attribute("IrmPrint").Value), System.Convert.ToBoolean(item.Attribute("IrmVBA").Value), System.Convert.ToBoolean(item.Attribute("IrmOffline").Value), System.Convert.ToInt32(item.Attribute("IrmOfflineDays").Value),
                   System.Convert.ToBoolean(item.Attribute("IrmReject").Value), System.Convert.ToBoolean(item.Attribute("IrmExpire").Value), item.Attribute("IrmExpireDate"));
                {
                    try {
                        mtr.TraceVerboseMessage("Updating irm for list with title = " + irmItem.ListInstance);
                        SPList list = web.Lists[irmItem.ListInstance];
                        list.IrmEnabled = irmItem.IrmEnabled;
                        list.IrmReject = irmItem.IrmReject;
                        list.IrmExpire = irmItem.IrmExpire;
                        SPFolder folder = list.RootFolder;
                        if (irmItem.IrmPrint) folder.Properties["vti_irm_IrmPrint"] = 2; else folder.Properties["vti_irm_IrmPrint"] = 0;
                        if (irmItem.IrmVBA) folder.Properties["vti_irm_IrmVBA"] = 2; else folder.Properties["vti_irm_IrmVBA"] = 0;
                        if (irmItem.IrmOffline) folder.Properties["vti_irm_IrmOffline"] = 2; else folder.Properties["vti_irm_IrmOffline"] = 0;
                        folder.Properties["vti_irm_IrmOfflineDays"] = irmItem.IrmOfflineDays;
                        if (irmItem.IrmExpireDate != null) {
                            try {
                                DateTime date = System.Convert.ToDateTime(irmItem.IrmExpireDate);
                                folder.Properties["vti_irm_IrmExpireDate"] = date.ToString("r", CultureInfo.InvariantCulture);
                            } catch (Exception) {
                                mtr.TraceVerboseMessage("Could not convert IrmExpireDate to a valid date. Continuing without setting IrmExpireDate");
                            }
                        }
                        folder.Properties["vti_irm_IrmTitle"] = irmItem.IrmTitle;
                        folder.Properties["vti_irm_IrmDescription"] = irmItem.IrmDescription;
                        mtr.TraceVerboseMessage("IrmTitle=" + irmItem.IrmTitle + " and vti_irm_IrmTitle=" + folder.Properties["vti_irm_IrmTitle"].ToString());
                        mtr.TraceVerboseMessage("Updating irm for list '" + irmItem.ListInstance + "' OK");
                        folder.Update();
                        list.Update();
                    } catch (Exception ex) {
                        mtr.TraceError("Unable to update irm for list " + irmItem.ListInstance, ex);
                        return false;
                    }
                }
                mtr.TraceVerboseMessage("ApplyIrmSettings() completed successfully");
                return true;
            } catch (Exception ex) {
                mtr.TraceError("ApplyIrmSettings() failed ", ex);
                return false;
            }
        }


        /// <summary>
        /// Apply what web templates should be available in the create new site dialog.
        /// This setting is per web
        /// </summary>
        /// <param name="web">The web to apply the changes</param>
        /// <param name="items">Collection of templates to add to the web</param>
        public static void ApplyAvailableWebTemplates(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting AvailableWebTemplates()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;

            try {
                if (item.Attribute("TemplateList") != null) {
                    string myName = String.Empty;
                    //SPWebTemplateCollection templates = web.GetAvailableWebTemplates((uint)1033, true);
                    SPWebTemplateCollection templates = web.Site.GetWebTemplates(web.Language);
                    Collection<SPWebTemplate> collection = new Collection<SPWebTemplate>();

                    string[] templateNameArray = item.Attribute("TemplateList").Value.Split(';');
                    if (templateNameArray.Length == 0) return; // no templates are specified, so return or else the list will be cleared of all templates.
                    foreach (SPWebTemplate template in templates) {
                        foreach (string s in templateNameArray) {
                            if (template.Name == s) {
                                collection.Add(template);
                                mtr.TraceVerboseMessage(string.Format("Adding: {0}", template.Name));
                            }
                        }

                    }
                    //web.SetAvailableWebTemplates(collection, (uint)1033);
                    web.SetAvailableWebTemplates(collection, (web.Language));
                    web.Update();
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to ApplyAvailableSiteTemplates. ", ex);

            }
        }

        /// <summary>
        /// Add web templates to be available including existing available templates.
        /// This setting is per web
        /// </summary>
        /// <param name="web">The web to apply the changes</param>
        /// <param name="items">Collection of templates to add to the web</param>
        public static void AddAvailableWebTemplate(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting AddWebTemplates()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;

            try {
                if (item.Attribute("TemplateList") != null) {
                    string myName = String.Empty;
                    SPWebTemplateCollection availableTemplates = web.GetAvailableWebTemplates(web.Language, true);
                    SPWebTemplateCollection templates = web.Site.GetWebTemplates(web.Language);
                    Collection<SPWebTemplate> collection = new Collection<SPWebTemplate>();

                    string[] templateNameArray = item.Attribute("TemplateList").Value.Split(';');
                    if (templateNameArray.Length == 0) return; // no templates are specified, so return or else the list will be cleared of all templates.

                    foreach (SPWebTemplate template in templates) {
                        // Add exisiting templates to collection
                        foreach (SPWebTemplate t in availableTemplates) {
                            //SPWebTemplate collectionTemplate = collection.FirstOrDefault(tC => tC.Name == template.Name); // Check if exist in collection already
                            if (t.Name.ToUpper() == template.Name.ToUpper()) {
                                collection.Add(template);
                            }
                        }
                        // Add new templates to collection
                        foreach (string s in templateNameArray) {
                            SPWebTemplate collectionTemplate = collection.FirstOrDefault(tC => tC.Name == template.Name); // Check if exist in collection already
                            if (collectionTemplate == null && s.ToUpper() == template.Name.ToUpper()) {
                                collection.Add(template);
                            }
                        }
                    }
                    //web.SetAvailableWebTemplates(collection, (uint)1033);
                    web.SetAvailableWebTemplates(collection, (web.Language));
                    web.Update();
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to AddAvailableSiteTemplates. ", ex);

            }
        }

        /// <summary>
        /// Remove templates from existing available templates.
        /// This setting is per web
        /// </summary>
        /// <param name="web">The web to apply the changes</param>
        /// <param name="items">Collection of templates to add to the web</param>
        public static void RemoveAvailableWebTemplate(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting RemoveWebTemplates()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;

            try {
                if (item.Attribute("TemplateList") != null) {
                    string myName = String.Empty;
                    SPWebTemplateCollection availableTemplates = web.GetAvailableWebTemplates(web.Language, true);
                    Collection<SPWebTemplate> collection = new Collection<SPWebTemplate>();

                    string[] templateNameArray = item.Attribute("TemplateList").Value.Split(';');
                    if (templateNameArray.Length == 0) return; // no templates are specified, so return or else the list will be cleared of all templates.

                    foreach (SPWebTemplate template in availableTemplates) {
                        string removedTemplate = templateNameArray.FirstOrDefault(tName => tName.ToUpper() == template.Name.ToUpper()); // Check if exist in templates to be removed
                        // Add templates that are not to be removed
                        if (removedTemplate == null) {
                            collection.Add(template);
                        }
                    }
                    //web.SetAvailableWebTemplates(collection, (uint)1033);
                    web.SetAvailableWebTemplates(collection, (web.Language));
                    web.Update();
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Unable to RemoveAvailableSiteTemplates. ", ex);

            }
        }

        /// <summary>
        /// Create a new roledefinition (permissionset)
        /// </summary>
        /// <param name="web">the web</param>
        /// <param name="item">collection of roledefinitionitems to create</param>
        public static void CreateRoleDefinition(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting CreateRoleDefinition");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            try {
                if (web.HasUniqueRoleAssignments == false) {
                    mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                    return;
                }
                if (item.Attribute("Name") != null) {
                    string permissionLevelName = item.Attribute("Name").Value;
                    mtr.TraceVerboseMessage("Creating permissionlevel: " + permissionLevelName);
                    // Create a new Permission Level
                    SPRoleDefinition newPermissionLevel = new SPRoleDefinition();
                    newPermissionLevel.Name = permissionLevelName;
                    if (item.Attribute("Description") != null) newPermissionLevel.Description = item.Attribute("Description").Value;

                    long permissionMask = 0;
                    foreach (XElement element in item.Descendants("{http://tempuri.org/siteconfigurator.xsd}Permission")) {
                        if (bool.Parse(element.Value)) // Add the item if it's value is set to true
                        {
                            foreach (string perm in Enum.GetNames(typeof(SPBasePermissions))) {
                                if (element.Attribute("Name").Value == perm) {
                                    permissionMask += (long)((SPBasePermissions)(Enum.Parse(typeof(SPBasePermissions), perm)));
                                }
                            }
                        }
                    }
                    newPermissionLevel.BasePermissions = (SPBasePermissions)(permissionMask);
                    mtr.TraceVerboseMessage("Done creating permissionlevel: " + permissionLevelName);
                    // Add the permission level to web
                    web.RoleDefinitions.Add(newPermissionLevel);
                    mtr.TraceVerboseMessage("Permissionlevel added to roledefinition.");
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Error in AddRoleDefinition", ex);
            }
        }
        /// <summary>
        /// Deletes a role definition
        /// </summary>
        /// <param name="web">the web</param>
        /// <param name="item">Collection of role to delete</param>
        public static void DeleteRoleDefinition(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting DeleteRoleDefinition");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            try {
                if (web.HasUniqueRoleAssignments == false) {
                    mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                    return;
                }
                //Create the new permission level
                if (item.Attribute("Name") != null) {
                    string permissionLevelName = item.Attribute("Name").Value;
                    // Delete the permission from the web
                    web.RoleDefinitions.Delete(permissionLevelName);
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Error in DeleteRoleDefinition", ex);
            }
        }
        /// <summary>
        /// Creates the default groups; Owners, Members and visitors.
        /// </summary>
        /// <param name="web">the web</param>
        /// <param name="item">settings for the creation process</param>
        public static void CreateDefaultAssociatedGroups(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting CreateDefaultAssociatedGroups");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            try {
                if (web.HasUniqueRoleAssignments == false) {
                    mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                    return;
                }
                if (item != null) {
                    if ((item.Attribute("userlogin") != null) && (item.Attribute("userlogin2") != null)) {
                        string userlogin = string.Empty;
                        string userlogin2 = string.Empty;
                        if (item.Attribute("userlogin").Value.ToLower().Equals("sitecollectionadministrator")) {
                            SPUserCollection oUserCollection = web.SiteAdministrators;
                            foreach (SPUser oSPUser in oUserCollection) {
                                if (oSPUser.IsSiteAdmin == true) {
                                    userlogin = oSPUser.LoginName;
                                    break;
                                }
                            }
                        }
                        //if (item.Attribute("userlogin").Value.ToLower().Equals("sitecollectionadministrator")) //check should be on userlogin2
                        if (item.Attribute("userlogin2").Value.ToLower().Equals("sitecollectionadministrator")) {
                            SPUserCollection oUserCollection = web.SiteAdministrators;
                            foreach (SPUser oSPUser in oUserCollection) {
                                if (oSPUser.IsSiteAdmin == true && oSPUser.LoginName != userlogin) {
                                    userlogin2 = oSPUser.LoginName;
                                    break;
                                }
                            }
                        }
                        string prefix = string.Empty;
                        if (item.Attribute("groupNameSeed") != null) prefix = item.Attribute("groupNameSeed").Value;
                        if (web.HasUniqueRoleAssignments) {
                            web.CreateDefaultAssociatedGroups(userlogin, userlogin2, prefix);
                            web.Properties.Update();
                        } else mtr.TraceVerboseMessage("Cannot create default associated groups on a site inheriting security settings");
                    }
                    web.Update();
                    mtr.TraceVerboseMessage("Completed CreateDefaultAssociatedGroups");
                }
            } catch (Exception ex) {

                mtr.TraceError("There was an error in CreateDefaultAssociatedGroups", ex);
            }
        }

        /// <summary>
        /// Create site collection groups
        /// </summary>
        /// <param name="web">Web to configure</param>
        /// <param name="items">items from the</param>
        public static void CreateSiteGroup(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting CreateSiteGroup");
            if (web.HasUniqueRoleAssignments == false) {
                mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                return;
            }
            try {
                #region CreateSiteGroup
                if (item.Attribute("Name") != null) {

                    mtr.TraceVerboseMessage(string.Format("Starting to CreateSiteGroup {0}", item.Attribute("Name").Value));
                    SPRoleDefinition role = web.RoleDefinitions[item.Attribute("Role").Value];
                    string userName = item.Attribute("DefaultUser").Value;

                    userName = ResolveUserOrGroupToken(web, userName, false);
                    #region Old way of resolving username - this code is already in the utility methods ResolveUserOrGroup
                    /*
                    // Handle usage of the special cases of roles instead of username in the configuration file
                    if (userName.ToLower().Equals("sitecollectionadministrator"))
                    {
                        SPUserCollection oUserCollection = web.AllUsers;
                        foreach (SPUser oSPUser in oUserCollection)
                        {
                            if (oSPUser.IsSiteAdmin == true)
                            {
                                userName = oSPUser.LoginName;
                                mtr.TraceVerboseMessage(string.Format("username set to sitecollectionadministrator: Found loginname: {0}.", userName));
                                break;
                            }
                        }
                    }
                    else if (userName.ToLower().Equals("siteowner"))
                    {
                        using (SPSite site = web.Site)
                        {
                            userName = site.Owner.LoginName;
                            mtr.TraceVerboseMessage(string.Format("Username set to siteowner: Found a loginname: {0}.", userName));
                        }
                    }
                    else if (userName.ToLower().Equals("null"))
                    {
                        userName = string.Empty;
                        mtr.TraceVerboseMessage("username set to null");
                    }
                     */
                    #endregion

                    string ownerName = item.Attribute("Owner").Value;
                    ownerName = ResolveUserOrGroupToken(web, ownerName, false);
                    #region  Old way of resolving ownername - this code is already in the utility methods ResolveUserOrGroup
                    /*
                    // Handle usage of the special cases of roles instead of username in the configuration file
                    if (ownerName.ToLower().Equals("sitecollectionadministrator")) {
                        SPUserCollection oUserCollection = web.SiteAdministrators;
                        foreach (SPUser oSPUser in oUserCollection) {
                            if (oSPUser.IsSiteAdmin == true) {
                                ownerName = oSPUser.LoginName;
                                mtr.TraceVerboseMessage(string.Format("ownername set to sitecollectionadministrator: Found a loginname: {0}.", ownerName));
                                break;
                            }
                        }
                    } else if (ownerName.ToLower().Equals("siteowner")) {
                        using (SPSite site = web.Site) {
                            ownerName = site.Owner.LoginName;
                            mtr.TraceVerboseMessage(string.Format("ownername set to sitecollectionadministrator: Found a loginame: {0}.", ownerName));
                        }
                    }
                     */
                    #endregion
                    // Handle usage of the special cases of roles instead of username in the configuration file


                    string description = string.Empty;
                    if (item.Attribute("Description") != null) description = item.Attribute("Description").Value;

                    string groupName = item.Attribute("Name").Value;
                    // Add site title to group name and ownername (implies a site group is being used), if the flag in the xml is true.
                    if (item.Attribute("AddSiteTitleToNames") != null) {
                        if (bool.Parse(item.Attribute("AddSiteTitleToNames").Value)) {
                            groupName = web.Title + " " + groupName;
                            groupName = NormalizeSharePointGroupName(groupName, web.Title);
                            mtr.TraceVerboseMessage(string.Format("GroupName updated with Sitetitle. New groupname is : {0}.", groupName));
                            if ((!ownerName.Contains('\\'))) // && (!ownerName.ToLower().Equals("sitecollectionadministrators")))
                            {
                                ownerName = web.Title + " " + ownerName;
                                ownerName = NormalizeSharePointGroupName(ownerName, web.Title);
                                mtr.TraceVerboseMessage(string.Format("Owner is a group and its name updated with site title. New name is: {0}.", ownerName));
                            }

                        }
                    }

                    //make sure the users exists before adding the group
                    SPMember owner;
                    if (ownerName.Contains('\\')) {
                        owner = web.EnsureUser(ownerName);
                        mtr.TraceVerboseMessage("Owner is a user, and ensured on the web.");
                    } else {
                        owner = web.Groups[ownerName];
                        mtr.TraceVerboseMessage("Owner is a group, and selected from the web.");
                    }

                    //Check if the group already exists:
                    if (!web.SiteGroups.Xml.Contains(string.Format("Name=\"{0}\"", groupName))) {
                        mtr.TraceVerboseMessage("The group does not exist in the Sitegroups xml");
                        if (!userName.Equals(string.Empty)) // => because you cannot call web.EnsureUser on an empty string.
                        {
                            SPUser user = web.EnsureUser(userName);
                            mtr.TraceVerboseMessage(string.Format("Default user: {0}, is not empty and the user is ensured on the web", userName));
                            web.SiteGroups.Add(groupName, owner, user, description);
                            mtr.TraceVerboseMessage(string.Format("Group {0} is added with owner: {1}, user: {2} and description: {3}", groupName, ownerName, userName, description));
                        } else {
                            mtr.TraceVerboseMessage("Default user is empty, adding group without");
                            web.SiteGroups.Add(groupName, owner, null, description);

                            mtr.TraceVerboseMessage(string.Format("Group {0} is added with owner: {1}, user: null and description: {2}", groupName, ownerName, description));
                        }
                    } else // the group exists, so just update it
                    {
                        mtr.TraceVerboseMessage("The group already exits, selecting it and updating...");
                        web.SiteGroups[groupName].Owner = owner;
                        mtr.TraceVerboseMessage(string.Format("Group: {0} updated with owner: {1}", groupName, ownerName));

                        if (!userName.Equals(string.Empty)) // => because you cannot call web.EnsureUser on an empty string.
                        {
                            mtr.TraceVerboseMessage("A default user is provided");
                            SPUser user = web.EnsureUser(userName);
                            mtr.TraceVerboseMessage(string.Format("Default user: {0}, is not empty and the user is ensured on the web", userName));
                            web.SiteGroups[groupName].AddUser(user);
                            mtr.TraceVerboseMessage(string.Format("Default user: {0}, is added to the group", userName));
                        }
                        web.SiteGroups[groupName].Description = description;
                        mtr.TraceVerboseMessage(string.Format("Description updated to: {0}", description));

                        //Should all members be allowed to add new members?
                        if (item.Attribute("AllowMembersEditMembership") != null) {
                            web.SiteGroups[groupName].AllowMembersEditMembership = bool.Parse(item.Attribute("AllowMembersEditMembership").Value);
                            mtr.TraceVerboseMessage(string.Format("AllowMembersEditMembership updated to: {0}", bool.Parse(item.Attribute("AllowMembersEditMembership").Value)));
                            web.SiteGroups[groupName].Update();
                        }
                        // Rename the group if specified:
                        if (item.Attribute("RenameGroupTo") != null) {
                            mtr.TraceVerboseMessage("Rename of group is specified. Starting...");
                            SPGroup oGroup = web.SiteGroups[groupName];
                            // Add site title to group name and ownername (implies a site group is being used), if the flag in the xml is true.
                            if (item.Attribute("AddSiteTitleToNames") != null) {
                                if (bool.Parse(item.Attribute("AddSiteTitleToNames").Value)) {
                                    groupName = web.Title + " " + item.Attribute("RenameGroupTo").Value;
                                    groupName = NormalizeSharePointGroupName(groupName, web.Title);
                                    mtr.TraceVerboseMessage("Groupname selected is: " + groupName);
                                } else {
                                    groupName = item.Attribute("RenameGroupTo").Value;
                                    mtr.TraceVerboseMessage("Groupname selected is: " + groupName);
                                }
                            } else {
                                groupName = item.Attribute("RenameGroupTo").Value;
                                mtr.TraceVerboseMessage("Groupname selected is: " + groupName);
                            }
                            oGroup.Name = groupName;
                            mtr.TraceVerboseMessage("Groupname updated to: " + groupName);
                            oGroup.Update();
                            mtr.TraceVerboseMessage("Group.Update() called");
                        }
                    }

                    mtr.TraceVerboseMessage("Selecting SPPrincipal for group");
                    SPPrincipal group = (SPPrincipal)web.SiteGroups[groupName];
                    if (web.RoleAssignments.RoleAssignmentExists(group)) {
                        mtr.TraceVerboseMessage("Found a roleassignment for the group");
                        SPRoleAssignment roleAssignment = web.RoleAssignments.GetAssignmentByPrincipal(group);

                        // Remove existing role definition bindings
                        roleAssignment.RoleDefinitionBindings.RemoveAll();
                        mtr.TraceVerboseMessage("Removed all existing roledefintionbindings");

                        // Add specified role definition binding
                        roleAssignment.RoleDefinitionBindings.Add(role);
                        mtr.TraceVerboseMessage("RoleDefinitionbinding added");
                        roleAssignment.Update();
                        mtr.TraceVerboseMessage("Roleassignment updated");
                    } else {
                        mtr.TraceVerboseMessage("Did not find a roleassignment for the group");
                        mtr.TraceVerboseMessage("Creating new roleassignment for the group");
                        SPRoleAssignment roleAssignment = new SPRoleAssignment(group);

                        // Add specified role definition binding
                        roleAssignment.RoleDefinitionBindings.Add(role);
                        mtr.TraceVerboseMessage("RoleDefinitionbinding added");
                        web.RoleAssignments.Add(roleAssignment);
                        mtr.TraceVerboseMessage("Roleassignment added");
                    }

                    if (item.Attribute("OnlyAllowMembersViewMembership") != null) {
                        try {
                            SPGroup oGroup = web.SiteGroups[groupName];
                            mtr.TraceVerboseMessage("Setting OnlyAllowMembersViewMembership for group: " + groupName);
                            oGroup.OnlyAllowMembersViewMembership = bool.Parse(item.Attribute("OnlyAllowMembersViewMembership").Value);
                            oGroup.Update();
                        } catch (Exception ex) {
                            mtr.TraceError("There was an error setting OnlyAllowMembersViewMembership", ex);
                        }
                    }
                    if (item.Attribute("AllowRequestToJoinLeave") != null) {
                        try {
                            SPGroup oGroup = web.SiteGroups[groupName];
                            mtr.TraceVerboseMessage("Setting AllowRequestToJoin for group: " + groupName);
                            oGroup.AllowRequestToJoinLeave = bool.Parse(item.Attribute("AllowRequestToJoinLeave").Value);
                            if (item.Attribute("AutoAcceptRequestToJoinLeave") != null) {
                                mtr.TraceVerboseMessage("Setting AutoAcceptRequestToJoinLeave for group: " + groupName);
                                oGroup.AutoAcceptRequestToJoinLeave = bool.Parse(item.Attribute("AutoAcceptRequestToJoinLeave").Value);
                            }
                            if ((oGroup.AllowRequestToJoinLeave) && (item.Attribute("RequestToJoinLeaveEmailSetting") != null)) {
                                string email = item.Attribute("RequestToJoinLeaveEmailSetting").Value;
                                if (email.Equals("SiteCollectionAdministrator")) {
                                    //Take the email of the first sitecollectionadministrator
                                    SPUserCollection oUserCollection = web.SiteAdministrators;
                                    foreach (SPUser oSPUser in oUserCollection) {
                                        if (oSPUser.IsSiteAdmin == true) {
                                            oGroup.RequestToJoinLeaveEmailSetting = oSPUser.Email;
                                            mtr.TraceVerboseMessage("Setting RequestToJoinLeaveEmailSetting for group: " + email);
                                            break;
                                        }

                                    }
                                } else {
                                    //Check the email is valid then add
                                    Regex matchRegex = new Regex(@"[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9_\-\.]+\.[a-zA-Z]{2,5}");
                                    if (matchRegex.IsMatch(email)) {
                                        oGroup.RequestToJoinLeaveEmailSetting = email;
                                        mtr.TraceVerboseMessage("Setting RequestToJoinLeaveEmailSetting for group: " + email);
                                    } else {
                                        oGroup.RequestToJoinLeaveEmailSetting = "NotValid@someEmailserver.com";
                                        mtr.TraceVerboseMessage("Setting RequestToJoinLeaveEmailSetting for group: NotValid@someEmailserver.com");
                                    }
                                }
                            }
                            oGroup.Update();
                        } catch (Exception ex) {
                            mtr.TraceError("There was an error setting AllowRequestToJoin", ex);
                        }
                    }
                    ////Add the group to the web's permission QL 
                    if (item.Attribute("AssociatedGroups") != null) {
                        try {
                            if (bool.Parse(item.Attribute("AssociatedGroups").Value)) {
                                SPGroup grp = web.SiteGroups[groupName];
                                if (!web.AssociatedGroups.Contains<SPGroup>(grp)) {
                                    //web.Properties.Update();
                                    web.AssociatedGroups.Add(grp);
                                    //web.Properties["vti_associategroups"] += ";" + grp.ID;
                                    web.AllProperties["vti_associategroups"] += ";" + grp.ID;
                                    //web.Update();
                                    //web.Properties.Update();
                                }
                            }
                        } catch (Exception ex) {
                            mtr.TraceError("There was an error setting AddToGroupsQuickLaunch", ex);
                        }
                    }
                }

                web.Update();
                #endregion
            } catch (Exception ex) {
                mtr.TraceError("There was an error creating a site group", ex);
            }
        }

        internal static void DeleteSiteGroup(SPWeb web, XElement item) {
            if (item.Attribute("Name") != null) {
                try {
                    SPGroupCollection groups = web.SiteGroups;
                    groups.Remove(item.Attribute("Name").Value);
                } catch (Exception ex) {
                    mtr.TraceError("There was en error trying to delete the SiteGroup:" + item.Attribute("Name").Value, ex);
                }
            }
        }
        public static void SetSecurityGroupQuickLaunch(SPWeb web, XElement item) {
            if (item == null) throw new ArgumentNullException("Item", "Cannot be null.");
            if (web == null) throw new ArgumentNullException("Web", "Cannot be null.");
            try {
                //Clear out all old groups if the config does not say keep them.
                if (!bool.Parse(item.Attribute("KeepExisting").Value))
                    web.AssociatedGroups.Clear();
                if (item.Attribute("Groups") != null) {
                    //splitt the semicolon seperated string into items
                    string[] grps = item.Attribute("Groups").Value.Split(';');
                    foreach (string s in grps) {
                        SPGroup grp = web.SiteGroups[s];
                        web.AssociatedGroups.Add(grp);
                        //web.Properties["vti_associategroups"] += ";" + grp.ID;
                        web.AllProperties["vti_associategroups"] += ";" + grp.ID;
                        web.Update();
                        // web.Properties.Update();
                    }
                }
            } catch (Exception ex) {
                mtr.TraceError("There was an error setting AddToGroupsQuickLaunch", ex);
            }
        }

        /// <summary>
        /// Creates information management policies for the site collection.
        /// </summary>
        /// <param name="site">The site.</param>
        /// <param name="item">The configuration items.</param>
        public static void CreateSiteCollectionInformationManagementPolicies(SPSite site, XElement item) {
            mtr.TraceVerboseMessage("Starting CreateSiteCollectionInformationManagementPolicies");
            if (site == null) throw new ArgumentNullException("site", "Cannot be null");
            if (item == null) return;
            try {
                //Create the new site collection information policy
                if (item.Attribute("Id") != null) {
                    string policyId = item.Attribute("Id").Value;
                    string policyManifest = item.Element("{http://tempuri.org/siteconfigurator.xsd}PolicyManifest").FirstNode.ToString();

                    PolicyCatalog policyCatalog = new PolicyCatalog(site);
                    Policy policy = policyCatalog.PolicyList[policyId];
                    if (policy == null) {
                        mtr.TraceVerboseMessage("Creating policy " + policyId);
                        Policy.ValidateManifest(policyManifest);
                        PolicyCollection.Add(site, policyManifest);
                    } else {
                        mtr.TraceVerboseMessage("Policy " + policyId + " already exists");
                    }
                }
            } catch (Exception ex) {
                mtr.TraceError("Error in CreateSiteCollectionInformationManagementPolicies. Check your configuration file.", ex);
            }
        }

        /// <summary>
        /// Creates the information management policies for the content types.
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="item">The configuration items.</param>
        public static void CreateContentTypeInformationManagementPolicies(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting CreateContentTypeInformationManagementPolicies");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            try {
                if (web.HasUniqueRoleAssignments == false) {
                    mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                    return;
                }
                //Create the new site collection information policy
                if (item.Attribute("ContentTypeId") != null) {
                    string contentTypeId = item.Attribute("ContentTypeId").Value;
                    string name = item.Attribute("Name").Value;
                    string description = item.Attribute("Description").Value;
                    string statement = item.Attribute("Statement").Value;

                    SPContentType contentType = null;
                    contentType = web.ContentTypes[new SPContentTypeId(contentTypeId)];


                    if (Policy.GetPolicy(contentType) != null) {
                        mtr.TraceVerboseMessage("Deleting existing policy for content type " + contentTypeId);
                        Policy.DeletePolicy(contentType);
                    }

                    // Create a new Policy 
                    mtr.TraceVerboseMessage("Creating policy for content type " + contentTypeId);
                    Policy.CreatePolicy(contentType, null);

                    Policy ctPolicy = Policy.GetPolicy(contentType);
                    ctPolicy.Name = name;
                    ctPolicy.Description = description;
                    ctPolicy.Statement = statement;

                    //Add policy features to the content type policy
                    foreach (XElement policyItem in item.Element("{http://tempuri.org/siteconfigurator.xsd}PolicyItems").Elements()) {
                        string policyFeatureId = policyItem.Attribute("FeatureId").Value;
                        mtr.TraceVerboseMessage("Adding policy feature " + policyFeatureId);
                        string customData = policyItem.Element("CustomData") != null && policyItem.Element("CustomData").FirstNode != null ? policyItem.Element("CustomData").FirstNode.ToString() : null;
                        ctPolicy.Items.Add(policyFeatureId, customData);
                    }
                }
            } catch (Exception ex) {
                mtr.TraceError("Error in CreateContentTypeInformationManagementPolicies. Check your configuration file.", ex);
            }
        }

        /// <summary>
        /// Adds the site collection information management policy association to the content type.
        /// </summary>
        /// <param name="site">The site.</param>
        /// <param name="web">The web.</param>
        /// <param name="item">The items.</param>
        public static void AddSiteCollectionInformationManagementPolicyContentTypeAssociations(SPSite site, SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting AddSiteCollectionInformationManagementPolicyContentTypeAssociations");
            try {
                if (web.HasUniqueRoleAssignments == false) {
                    mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                    return;
                }
                //Add the site collection information policy content type association
                if (item.Attribute("ContentTypeId") != null && item.Attribute("PolicyId") != null) {
                    string contentTypeId = item.Attribute("ContentTypeId").Value;
                    string policyId = item.Attribute("PolicyId").Value;

                    PolicyCatalog policyCatalog = new PolicyCatalog(site);
                    Policy policy = policyCatalog.PolicyList[policyId];
                    if (policy == null) {
                        mtr.TraceVerboseMessage("Site collection policy " + policyId + " doesn't exist. Unable to associate with content type " + contentTypeId);
                    } else {
                        SPContentType contentType = web.ContentTypes[new SPContentTypeId(contentTypeId)];
                        mtr.TraceVerboseMessage("Setting the content type to readonly = false, in order to be able to configure it.");
                        contentType.ReadOnly = false;
                        Policy existingPolicy = Policy.GetPolicy(contentType);
                        if (existingPolicy != null) {
                            mtr.TraceVerboseMessage("Deleting existing policy " + existingPolicy.Id + " for content type " + contentTypeId);
                            Policy.DeletePolicy(contentType);
                        }
                        mtr.TraceVerboseMessage("Associating policy " + policyId + " with content type " + contentTypeId);
                        Policy.CreatePolicy(contentType, policy);
                    }
                }
            } catch (Exception ex) {
                mtr.TraceError("Error in AddSiteCollectionInformationManagementPolicyContentTypeAssociations. Check your configuration file.", ex);
            }
        }

        /// <summary>
        /// Add users or groups to the specified group.
        /// Use "SiteCollectionAdministrators" for adding to the sitecollection admin group.
        /// </summary>
        /// <param name="web">web to update</param>
        /// <param name="item">group name and semicolon seperated strings of users (groupnames) to add to each group</param>
        /// <param name="siteCollAdmins">The site collection administrators, if specified.</param>
        public static void AddUserToGroup(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting AddUserToGroup()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            if (web.HasUniqueRoleAssignments == false) {
                mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                return;
            }

            try {
                // Check if applicable to root web, sub web, or both
                if ((item.Attribute("RootWebOnly") == null && item.Attribute("SubWebOnly") == null) ||
                    (item.Attribute("RootWebOnly") != null && ((item.Attribute("RootWebOnly").Value.ToUpperInvariant().Equals("TRUE") && web.IsRootWeb) || item.Attribute("RootWebOnly").Value.ToUpperInvariant().Equals("FALSE"))) ||
                    (item.Attribute("SubWebOnly") != null && ((item.Attribute("SubWebOnly").Value.ToUpperInvariant().Equals("TRUE") && !web.IsRootWeb) || item.Attribute("SubWebOnly").Value.ToUpperInvariant().Equals("FALSE")))) {
                    if (item.Attribute("GroupName") != null) {
                        string groupName = item.Attribute("GroupName").Value;
                        bool addSiteTitleToGroupNames = item.Attribute("AddSiteTitleToGroupNames") != null && item.Attribute("AddSiteTitleToGroupNames").Value.ToUpperInvariant().Equals("TRUE") ? true : false;

                        if (addSiteTitleToGroupNames) {
                            groupName = web.Title + " " + groupName;
                            groupName = NormalizeSharePointGroupName(groupName, web.Title);
                        }

                        if (web.SiteGroups.Xml.Contains(string.Format("Name=\"{0}\"", groupName))) {
                            string[] userNameArray = item.Attribute("Users").Value.Split(';');
                            foreach (string memberItem in userNameArray) {
                                try {
                                    string resolvedMember = ResolveUserOrGroupToken(web, memberItem, addSiteTitleToGroupNames);

                                    // if user is a user, make sure the user exists on this web and add
                                    if (resolvedMember.Contains('\\')) web.SiteGroups[groupName].AddUser(web.EnsureUser(resolvedMember));
                                    // else if a group is beining added, make sure it exists in the group collection first
                                    else if (web.SiteGroups.Xml.Contains(string.Format("Name=\"{0}\"", resolvedMember))) {
                                        SPMember group = web.Groups[resolvedMember];
                                        web.SiteGroups[groupName].AddUser((SPUser)group);
                                    } else mtr.TraceVerboseMessage(string.Format("Could not add user {0} to the group {1}", resolvedMember, groupName));
                                } catch (Exception ex) {
                                    mtr.TraceError(string.Format("Could not add user {0} to the group {1}", memberItem, groupName), ex);
                                }
                            }
                        } else if ((groupName.ToLower() == "sitecollectionadministrators")) {
                            List<string> currentMembers = new List<string>();
                            foreach (SPUser user in web.SiteAdministrators) {
                                currentMembers.Add(user.LoginName);
                            }

                            string[] userNameArray = item.Attribute("Users").Value.Split(';');
                            foreach (string memberItem in userNameArray) {
                                try {
                                    string resolvedMember = ResolveUserOrGroupToken(web, memberItem, addSiteTitleToGroupNames);
                                    if (resolvedMember.Contains('\\')) {
                                        SPUser member = web.EnsureUser(resolvedMember);
                                        member.IsSiteAdmin = true;
                                        member.Update();
                                        currentMembers.Remove(resolvedMember);
                                        mtr.TraceVerboseMessage(string.Format("Added user {0} to the group {1}", resolvedMember, groupName));
                                    }
                                        // else if a group is beining added, make sure it exists in the group collection first
                                    else if (web.SiteGroups.Xml.Contains(string.Format("Name=\"{0}\"", resolvedMember))) {
                                        web.SiteAdministrators.Add(memberItem, "", "", "");
                                        mtr.TraceVerboseMessage(string.Format("Added group {0} to the group {1}", resolvedMember, groupName));
                                    } else mtr.TraceVerboseMessage(string.Format("Could not add user {0} to the group {1}", resolvedMember, groupName));
                                } catch (Exception ex) {
                                    mtr.TraceError(string.Format("Could not add user {0} to the group {1}", memberItem, groupName), ex);
                                }
                            }

                            // Removing all users that were in the group before adding the ones from the configuration
                            foreach (string loginNameToRemove in currentMembers) {
                                SPUser userToRemove = web.AllUsers[loginNameToRemove];
                                userToRemove.IsSiteAdmin = false;
                                userToRemove.Update();
                                mtr.TraceVerboseMessage(string.Format("Removed user {0} from the group {1}", loginNameToRemove, groupName));
                            }
                        } else mtr.TraceVerboseMessage(string.Format("Cannot find {0} group, hence not adding any user(s) to this group", groupName));
                    }
                }
            } catch (Exception ex) {
                mtr.TraceError("An error occured in AddUserToGroup", ex);
            }
        }
        /// <summary>
        /// Add users or groups to the specified group.
        /// Use "SiteCollectionAdministrators" for adding to the sitecollection admin group.
        /// </summary>
        /// <param name="web">web to update</param>
        /// <param name="item">group name and semicolon seperated strings of users (groupnames) to add to each group</param>
        /// <param name="siteCollAdmins">The site collection administrators, if specified.</param>
        public static void AddUserToGroupFromGroup(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting AddUserToGroupFromGroup()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            if (web.HasUniqueRoleAssignments == false) {
                mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                return;
            }

            try {
                if (item.Attribute("GroupName") != null && (item.Attribute("FromGroupName")) != null) {
                    string groupName = item.Attribute("GroupName").Value;
                    string fromGroupName = item.Attribute("FromGroupName").Value;

                    bool addSiteTitleToGroupNames = item.Attribute("AddSiteTitleToGroupNames") != null && item.Attribute("AddSiteTitleToGroupNames").Value.ToUpperInvariant().Equals("TRUE") ? true : false;

                    mtr.TraceVerboseMessage("Get site collection for web.");

                    using (SPSite site = new SPSite(web.Site.Url)) {
                        using (SPWeb siteWeb = site.OpenWeb()) {
                            if (addSiteTitleToGroupNames) {
                                groupName = web.Title + " " + groupName;
                                groupName = NormalizeSharePointGroupName(groupName, web.Title);
                            }
                            if (addSiteTitleToGroupNames) {
                                fromGroupName = siteWeb.Title + " " + fromGroupName;
                                fromGroupName = NormalizeSharePointGroupName(fromGroupName, siteWeb.Title);
                            }
                            if (siteWeb.SiteGroups.Xml.Contains(string.Format("Name=\"{0}\"", fromGroupName))) {
                                SPUserCollection userFromGroup = siteWeb.SiteGroups[fromGroupName].Users;

                                if (web.SiteGroups.Xml.Contains(string.Format("Name=\"{0}\"", groupName))) {
                                    foreach (SPUser user in userFromGroup) {
                                        try {
                                            web.SiteGroups[groupName].AddUser(user);
                                        } catch (Exception ex) {
                                            mtr.TraceError(string.Format("Could not add user {0} to the group {1}", user.LoginName, groupName), ex);
                                        }

                                    }
                                } else mtr.TraceVerboseMessage(string.Format("Cannot find {0} group, hence not adding any user(s) to this group", groupName));

                            } else mtr.TraceVerboseMessage(string.Format("Cannot find {0} group, can't get any user from this group to add to {1} group", fromGroupName, groupName));
                        }
                    }
                }

            } catch (Exception ex) {
                mtr.TraceError("An error occured in AddUserToGroupFromGroup", ex);
            }
        }
        /// <summary>
        /// Resolves the user or group token to a specific user, or group name.
        /// Supported tokens:
        /// SiteCollectionAdministrator
        /// SiteOwner
        /// SiteCreator
        /// </summary>
        /// <param name="web">The web.</param>
        /// <param name="tokenName">The token to resolve.</param>
        /// <param name="addSiteTitleToGroupName"><c>True</c> to add the site title in front of the group name, <c>false</c> to use the site name as-is. Not in use for users.</param>
        /// <returns>The resolved user or group name.</returns>
        private static string ResolveUserOrGroupToken(SPWeb web, string tokenName, bool addSiteTitleToGroupName) {
            string resolvedTokenName = string.Empty;
            // Token representing the site collection administrator
            if (tokenName.ToUpperInvariant().Equals("SITECOLLECTIONADMINISTRATOR")) {
                SPUserCollection oUserCollection = web.AllUsers;
                foreach (SPUser oSPUser in oUserCollection) {
                    if (oSPUser.IsSiteAdmin == true) {
                        resolvedTokenName = oSPUser.LoginName;
                        mtr.TraceVerboseMessage(string.Format("TokenName sitecollectionadministrator resolved to loginname {0}.", resolvedTokenName));
                        break;
                    }
                }
            }
                // Token representing the owner of the site
            else if (tokenName.ToUpperInvariant().Equals("SITEOWNER")) {
                using (SPSite site = web.Site) {
                    resolvedTokenName = site.Owner.LoginName;
                    mtr.TraceVerboseMessage(string.Format("TokenName siteowner resolved to loginname {0}.", resolvedTokenName));
                }
            }
                // Token representing the creator of the site
            else if (tokenName.ToUpperInvariant().Equals("SITECREATOR")) {
                resolvedTokenName = web.Author.LoginName;
                mtr.TraceVerboseMessage(string.Format("TokenName sitecreator resolved to loginname {0}.", resolvedTokenName));
            } else if (tokenName.ToUpperInvariant().Equals("NULL")) {
                resolvedTokenName = string.Empty;
                mtr.TraceVerboseMessage("TokenName 'null' resolved to loginname 'String.Empty'");
            }
                // No token to replace, type is group, return name with or without site name as prefix
            else if (!tokenName.Contains('\\')) {
                if (addSiteTitleToGroupName) {
                    resolvedTokenName = web.Title + " " + tokenName;
                    resolvedTokenName = NormalizeSharePointGroupName(resolvedTokenName, web.Title);
                    mtr.TraceVerboseMessage(string.Format("TokenName resolved to group name {0}.", resolvedTokenName));
                } else {
                    resolvedTokenName = tokenName;
                    mtr.TraceVerboseMessage(string.Format("TokenName resolved to group name {0}.", resolvedTokenName));
                }
            }
                // No token to replace, type is user, return username
            else {
                resolvedTokenName = tokenName;
                mtr.TraceVerboseMessage(string.Format("TokenName resolved to loginname {0}.", resolvedTokenName));
            }
            return resolvedTokenName;
        }


        internal static void SetSiteCollectionAdministrators(SPWeb web, XElement item, XElement webConfigOverrideSection) {
            mtr.TraceVerboseMessage("Starting SetSiteCollectionAdministrators");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            if (web.HasUniqueRoleAssignments == false) {
                mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                return;
            }
            if (item != null) {
                //Check if this item accepts override and if so get the override item
                if (bool.Parse(item.Attribute("AllowWebConfigOverride").Value)) {
                    item = GetSiteCollectionAdministrators(item, webConfigOverrideSection);
                }
                try {
                    List<string> currentMembers = new List<string>();
                    foreach (SPUser user in web.SiteAdministrators) {
                        currentMembers.Add(user.LoginName.ToLower());
                    }

                    string[] userNameArray = item.Attribute("Users").Value.ToLower().Split(';');
                    foreach (string memberItem in userNameArray) {
                        try {
                            if (memberItem.Contains('\\')) {
                                SPUser member = web.EnsureUser(memberItem);
                                member.IsSiteAdmin = true;
                                member.Update();
                                mtr.TraceVerboseMessage(string.Format("Added user {0} to the Site Collection Administrators group.", memberItem));
                                currentMembers.Remove(memberItem);
                                mtr.TraceVerboseMessage(string.Format("Removed user {0} from the list of user to remove from the sitecollectionadministrators group.", memberItem));
                            } else mtr.TraceVerboseMessage(string.Format("Could not add user/group {0} to the Site Collection Administrators group. Either domain name is missing, or the group doesn't exist in the site. No domain specified.", memberItem));
                        } catch (Exception ex) {
                            mtr.TraceError(string.Format("Could not add user/group {0} to the Site Collection Administrators group", memberItem), ex);
                        }
                    }

                    // Removing all users that were in the group before adding the ones from the configuration
                    foreach (string loginNameToRemove in currentMembers) {
                        SPUser userToRemove = web.AllUsers[loginNameToRemove];
                        userToRemove.IsSiteAdmin = false;
                        userToRemove.Update();
                        web.SiteUsers.Remove(loginNameToRemove);
                        web.Update();
                        mtr.TraceVerboseMessage(string.Format("Removed user {0} from the Site Collection Administrators group, and the site.", loginNameToRemove));
                    }
                } catch (Exception ex) {
                    mtr.TraceError("An error occured in SetSiteCollectionAdministrators", ex);
                }
            }
        }
        /// <summary>
        /// Gets the list of users to set as site collection administrators.
        /// </summary>
        /// <param name="siteConfigSiteCollectionAdministratorsItem">The SetSiteCollectionAdministrators item from the site configuration.</param>
        /// <param name="overrideConfigSiteCollectionAdministratorsItem">The SetSiteCollectionAdministrators item from the web.config site configuration override.</param>
        /// <returns>
        /// The SetSiteCollectionAdministrators item to use for setting site collection administrators.
        /// </returns>
        private static XElement GetSiteCollectionAdministrators(XElement siteConfigSiteCollectionAdministratorsItem, XElement overrideConfigSiteCollectionAdministratorsItem) {
            mtr.TraceVerboseMessage("Starting GetSetSiteCollectionAdministrators (XElement siteConfigSiteCollectionAdministratorsItem, XElement overrideConfigSiteCollectionAdministratorsItem)");
            if (siteConfigSiteCollectionAdministratorsItem != null) {
                mtr.TraceVerboseMessage("Checking if webconfigattributeOverride attribute is set to true");
                if (siteConfigSiteCollectionAdministratorsItem.Attribute("AllowWebConfigOverride") != null && bool.Parse(siteConfigSiteCollectionAdministratorsItem.Attribute("AllowWebConfigOverride").Value) == true) {
                    //parse the SetSiteCollectionAdministrators item from the override section
                    mtr.TraceVerboseMessage("OK: webconfigattributeOverride = 'true'");
                    overrideConfigSiteCollectionAdministratorsItem = GetSetSiteCollectionAdministrators(overrideConfigSiteCollectionAdministratorsItem);
                    return overrideConfigSiteCollectionAdministratorsItem != null ? overrideConfigSiteCollectionAdministratorsItem : siteConfigSiteCollectionAdministratorsItem;
                } else {
                    return siteConfigSiteCollectionAdministratorsItem;
                }
            } else {
                return null;
            }
        }
        private static XElement GetSetSiteCollectionAdministrators(XElement section) {
            mtr.TraceVerboseMessage("Starting GetSetSiteCollectionAdministrators(XElement section)");
            mtr.TraceVerboseMessage("Creating empty Xelement");
            XElement item = null;
            try {
                if (section != null) {
                    mtr.TraceVerboseMessage("Using linq to select items from the ovveridesection - if present");
                    IEnumerable<XElement> configurationXML =
                            from s in section.Elements("SetSiteCollectionAdministrators")
                            select s;
                    mtr.TraceVerboseMessage("It is only allowed with one overrideitem, so selecting the FirstOrDefault.");
                    item = configurationXML.FirstOrDefault();
                }
            } catch (Exception ex) {
                mtr.TraceError("An error occured in GetSiteCollectionAdministrators(XElement setion)", ex);
            }
            mtr.TraceVerboseMessage("Returning override item");
            return item;

        }

        public static void CreateSubSite(SPWeb web, XElement item, XElement overridesection) {
            mtr.TraceVerboseMessage("Starting CreateSubSite()");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            try {
                if (item.Attribute("Url") == null) throw new ArgumentNullException("Url", "Cannot be null");
                string webUrl = item.Attribute("Url").Value;

                if (item.Attribute("Title") == null) throw new ArgumentNullException("Title", "Cannot be null");
                string title = item.Attribute("Title").Value;

                if (item.Attribute("Description") == null) throw new ArgumentNullException("Description", "Cannot be null");
                string description = item.Attribute("Description").Value;

                if (item.Attribute("Template") == null) throw new ArgumentNullException("Template", "Cannot be null");
                string template = item.Attribute("Template").Value;

                if (item.Attribute("UseUniquePermissions") == null) throw new ArgumentNullException("UseUniquePermissions", "Cannot be null");
                bool UseUniquePermissions = bool.Parse(item.Attribute("UseUniquePermissions").Value);
                mtr.TraceVerboseMessage(string.Format("Adding web with the following parameters {0}, {1}, {2}, {3}, {4}, {5}, false", webUrl, title, description, web.Language, template, UseUniquePermissions));
                SPWeb w = web.Webs.Add(webUrl, title, description, web.Language, template, UseUniquePermissions, false);

                if (item.Attribute("UseSharedNavigation") == null) throw new ArgumentNullException("UseSharedNavigation", "Cannot be null");
                bool UseSharedNavigation = bool.Parse(item.Attribute("UseSharedNavigation").Value);

                w.Navigation.UseShared = UseSharedNavigation;

                mtr.TraceVerboseMessage(string.Format("Starting subsite methods for web {0}, {1}", webUrl, title));
                SubSiteWebMethodsDynamic(w, item, overridesection);

                w.Update();
                w.Close();
            } catch (Exception e) {
                mtr.TraceError("There was an error creating a subweb", e);
            }
        }

        internal static string NormalizeSharePointGroupName(string name, string webTitle) {
            name = name.Trim();
            int num = name.Length - 0xff;
            if (num > 0) {
                name = name.Replace(webTitle, webTitle.Substring(0, webTitle.Length - num));
                if (name.Length > 0xff) {
                    name = name.Substring(0, 0xff);
                }
            }
            char[] chArray = name.ToCharArray();
            for (int i = 0; i < chArray.Length; i++) {
                if ("/\\[]:|<>+=;,?*'\"@".IndexOf(chArray[i]) >= 0) {
                    chArray[i] = '_';
                }
            }
            return new string(chArray);
        }


        /// <summary>
        /// Updates a role definition
        /// </summary>
        /// <param name="web">the web</param>
        /// <param name="item">Collection of role to update</param>
        public static void UpdateRoleDefinition(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting UpdateRoleDefinition");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;
            try {
                if (web.HasUniqueRoleAssignments == false) {
                    mtr.TraceVerboseMessage("This web inherits permissions, exiting method.");
                    return;
                }
                //Create the new permission level
                if (item.Attribute("Name") != null) {
                    string permissionLevelName = item.Attribute("Name").Value;
                    // Delete the permission from the web
                    SPRoleDefinition roleDefinition = web.RoleDefinitions[permissionLevelName];
                    if (roleDefinition != null) {
                        long permissionMask = (long)roleDefinition.BasePermissions;
                        foreach (XElement element in item.Descendants("{http://tempuri.org/siteconfigurator.xsd}Permission")) {
                            if (bool.Parse(element.Value)) // Add the item if it's value is set to true
                            {
                                foreach (string perm in Enum.GetNames(typeof(SPBasePermissions))) {
                                    if (element.Attribute("Name").Value == perm) {
                                        permissionMask += (long)((SPBasePermissions)(Enum.Parse(typeof(SPBasePermissions), perm)));
                                        break;
                                    }
                                }
                            } else {
                                foreach (string perm in Enum.GetNames(typeof(SPBasePermissions))) {
                                    if (element.Attribute("Name").Value == perm) // Subtract if the value is set to false
                                    {
                                        permissionMask -= (long)((SPBasePermissions)(Enum.Parse(typeof(SPBasePermissions), perm)));
                                        break;
                                    }
                                }
                            }
                        }
                        roleDefinition.BasePermissions = (SPBasePermissions)(permissionMask);
                        roleDefinition.Update();
                        mtr.TraceVerboseMessage("Done updating role definition: " + permissionLevelName);
                    }
                }
                web.Update();
            } catch (Exception ex) {
                mtr.TraceError("Error in UpdateRoleDefinition", ex);
            }
        }

        public static void AddContentTypeBinding(SPWeb web, XElement item) {
            mtr.TraceVerboseMessage("Starting AddContentTypeBinding");
            if (web == null) throw new ArgumentNullException("web", "Cannot be null");
            if (item == null) return;

            try {
                SPContentTypeId contentTypeId;
                string listUrl;
                if (item.Attribute("ContentTypeId") != null && item.Attribute("ListUrl") != null) {
                    contentTypeId = new SPContentTypeId(item.Attribute("ContentTypeId").Value);
                    listUrl = item.Attribute("ListUrl").Value;
                } else {
                    return;
                }

                SPList list = web.GetList(listUrl);
                SPContentType mytype = web.AvailableContentTypes[contentTypeId];
                list.ContentTypesEnabled = true;
                list.ContentTypes.Add(mytype);
                list.Update();
            } catch (Exception ex) {
                mtr.TraceError("Error in AddContentTypeBinding", ex);
            }

        }

        public static void ConfigureSubSite(SPSite site, XElement item, XElement overridesection) {
            mtr.TraceVerboseMessage("Starting ConfigureSubSite()");
            if (site == null) throw new ArgumentNullException("site", "Cannot be null");
            if (item == null) return;
            try {
                if (item.Attribute("Url") == null) throw new ArgumentNullException("Url", "Cannot be null");
                string webUrl = item.Attribute("Url").Value;

                using (SPWeb web = site.OpenWeb(webUrl)) {
                    mtr.TraceVerboseMessage(string.Format("Starting subsite methods for web {0}, {1}", webUrl, web.Title));
                    SubSiteWebMethodsDynamic(web, item, overridesection);
                }
            } catch (Exception e) {
                mtr.TraceError("There was an error configuring a subweb", e);
            }
        }
        /// <summary>
        /// Loads the methods in the order the properties in the siteconfiguration files is listed.
        /// </summary>
        private static void SubSiteWebMethodsDynamic(SPWeb web, XElement item, XElement overridesection) {
            IEnumerable<XElement> subItems = item.Elements();
            mtr.TraceVerboseMessage("Sub site Metods Dynamic started for subsite");

            foreach (XElement subItem in subItems) {
                try {
                    WebMethodsDynamic(web, subItem, overridesection);

                } catch (Exception ex) {
                    mtr.TraceError("Failed to apply the configuration element : " + item.ToString(), ex);
                }
            }
        }
        /// <summary>
        /// Loads the web methods in the order the properties in the siteconfiguration files is listed.
        /// </summary>
        public static void WebMethodsDynamic(SPWeb web, XElement item, XElement overridesection) {
            mtr.TraceVerboseMessage("Web Metods Dynamic started for web");
            try {
                #region switch
                string configPropertyName = item.Name.LocalName;
                switch (configPropertyName) {
                    case "AddUserToGroup":
                        SharePointUtilities.AddUserToGroup(web, item);
                        break;
                    case "AddUserToGroupFromGroup":
                        SharePointUtilities.AddUserToGroupFromGroup(web, item);
                        break;
                    case "AvailableWebTemplates":
                        SharePointUtilities.ApplyAvailableWebTemplates(web, item);
                        break;
                    case "AddWebTemplates":
                        SharePointUtilities.AddAvailableWebTemplate(web, item);
                        break;
                    case "RemoveWebTemplates":
                        SharePointUtilities.RemoveAvailableWebTemplate(web, item);
                        break;
                    case "ContentTypeInformationManagementPolicy":
                        SharePointUtilities.CreateContentTypeInformationManagementPolicies(web, item);
                        break;
                    case "DefaultAssociatedGroups":
                        SharePointUtilities.CreateDefaultAssociatedGroups(web, item);
                        break;
                    case "FileToProvision":
                        SharePointUtilities.ProvisionFile(web, item);
                        break;
                    case "ListInstance":
                        SharePointUtilities.CreateList(web, item);
                        break;
                    case "DeleteListInstance":
                        SharePointUtilities.DeleteList(web, item);
                        break;
                    case "Views":
                        SharePointUtilities.CreateViews(web, item);
                        break;
                    case "CustomListField":
                        SharePointUtilities.CreateCustomListFields(web, item);
                        break;
                    case "RoleDefinition":
                        SharePointUtilities.CreateRoleDefinition(web, item);
                        break;
                    case "RoleDefinitionToDelete":
                        SharePointUtilities.DeleteRoleDefinition(web, item);
                        break;
                    case "RoleDefinitionToUpdate":
                        SharePointUtilities.UpdateRoleDefinition(web, item);
                        break;
                    case "RoleInheritance":
                        SharePointUtilities.SetRoleInheritance(web, item);
                        break;
                    case "SiteGroup":
                        SharePointUtilities.CreateSiteGroup(web, item);
                        break;
                    case "DeleteSiteGroup":
                        SharePointUtilities.DeleteSiteGroup(web, item);
                        break;
                    case "TopNavigationToDelete":
                        SharePointUtilities.DeleteTopNavigationLinks(web);
                        break;
                    case "TopNavigationLink":
                        SharePointUtilities.AddTopNavigationLink(web, item);
                        break;
                    case "WebProperty":
                        SharePointUtilities.SetWebProperty(web, item);
                        break;
                    case "SiteCollectionFeature":
                        SharePointUtilities.ActivateSiteCollectionFeature(web, item);
                        break;
                    case "WebFeature":
                        SharePointUtilities.ActivateWebFeature(web, item);
                        break;
                    case "ApplyTheme":
                        SharePointUtilities.ApplyTheme(web, item);
                        break;
                    case "IrmSettings":
                        SharePointUtilities.ApplyIrmSetting(web, item);
                        break;
                    case "ListViewWebPart":
                        SharePointUtilities.AddListViewWebPart(web, item);
                        break;
                    case "RegionalSetting":
                        SharePointUtilities.SetRegionalSetting(web, item);
                        break;
                    case "DeleteQuickLaunchHeading":
                        SharePointUtilities.DeleteQuickLaunchHeading(web, item);
                        break;
                    case "DeleteExplicitTopNavigationLinks":
                        SharePointUtilities.DeleteExplicitTopNavigationLinks(web, item);
                        break;
                    case "DeleteQuickLaunchLinks":
                        SharePointUtilities.DeleteQuickLaunchLinks(web);
                        break;
                    case "DeleteQuickLaunchLinkItem":
                        SharePointUtilities.DeleteQuickLaunchLinkItem(web, item);
                        break;
                    case "QuickLaunchHeading":
                        SharePointUtilities.AddQuickLaunchHeading(web, item);
                        break;
                    case "QuickLaunchLink":
                        SharePointUtilities.AddQuickLaunchLink(web, item);
                        break;
                    case "AllUsersWebPart":
                        SharePointUtilities.AddWebPart(web, item, overridesection);
                        break;
                    case "DeleteWebPart":
                        SharePointUtilities.DeleteWebPart(web, item);
                        break;
                    case "RenameWebPart":
                        SharePointUtilities.RenameWebPart(web, item);
                        break;
                    case "PropertyBag":
                        SharePointUtilities.UpdatePropertyBag(web, item, overridesection);
                        break;
                    case "AllPropertyBag":
                        SharePointUtilities.UpdateAllPropertyBagItem(web, item, overridesection);
                        break;
                    case "PublishingNavigation":
                        SharePointUtilities.ConfigurePublishingNavigation(web, item);
                        break;
                    case "CreateSubSite":
                        SharePointUtilities.CreateSubSite(web, item, overridesection);
                        break;
                    case "MasterPageUrl":
                        SharePointUtilities.SetMasterUrlProperty(web, item);
                        break;
                    case "SecurityGroupQuickLaunch":
                        SharePointUtilities.SetSecurityGroupQuickLaunch(web, item);
                        break;
                    case "ContentTypeBinding":
                        SharePointUtilities.AddContentTypeBinding(web, item);
                        break;
                    default: // do nothing...
                        break;
                }
                #endregion

            } catch (Exception ex) {
                mtr.TraceError("Failed to apply the web configuration element : " + item.ToString(), ex);
            }
        }
    }
}

